touchdesigner-mcp-server 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +211 -0
  3. package/README.md +204 -0
  4. package/dist/api/customInstance.js +18 -0
  5. package/dist/cli.js +36 -0
  6. package/dist/core/constants.js +26 -0
  7. package/dist/core/errorHandling.js +19 -0
  8. package/dist/core/logger.js +45 -0
  9. package/dist/core/result.js +12 -0
  10. package/dist/features/prompts/handlers/td_prompts.js +131 -0
  11. package/dist/features/prompts/index.js +1 -0
  12. package/dist/features/prompts/register.js +7 -0
  13. package/dist/features/tools/handlers/tdTools.js +214 -0
  14. package/dist/features/tools/index.js +1 -0
  15. package/dist/features/tools/register.js +7 -0
  16. package/dist/features/tools/types.js +1 -0
  17. package/dist/features/tools/utils/toolUtils.js +1 -0
  18. package/dist/gen/endpoints/TouchDesignerAPI.js +250 -0
  19. package/dist/gen/mcp/touchDesignerAPI.zod.js +203 -0
  20. package/dist/index.js +3 -0
  21. package/dist/mock/index.js +5 -0
  22. package/dist/mock/node.js +3 -0
  23. package/dist/server/connectionManager.js +83 -0
  24. package/dist/server/touchDesignerServer.js +60 -0
  25. package/dist/tdClient/index.js +6 -0
  26. package/dist/tdClient/touchDesignerClient.js +150 -0
  27. package/package.json +76 -0
  28. package/src/index.ts +6 -0
  29. package/td/genHandlers.js +47 -0
  30. package/td/import_modules.py +52 -0
  31. package/td/mcp_webserver_base.tox +0 -0
  32. package/td/modules/mcp/controllers/__init__.py +9 -0
  33. package/td/modules/mcp/controllers/api_controller.py +623 -0
  34. package/td/modules/mcp/controllers/generated_handlers.py +365 -0
  35. package/td/modules/mcp/controllers/openapi_router.py +265 -0
  36. package/td/modules/mcp/services/__init__.py +8 -0
  37. package/td/modules/mcp/services/api_service.py +535 -0
  38. package/td/modules/mcp_webserver_script.py +134 -0
  39. package/td/modules/td_server/.dockerignore +72 -0
  40. package/td/modules/td_server/.openapi-generator/FILES +55 -0
  41. package/td/modules/td_server/.openapi-generator/VERSION +1 -0
  42. package/td/modules/td_server/.openapi-generator-ignore +23 -0
  43. package/td/modules/td_server/.travis.yml +14 -0
  44. package/td/modules/td_server/Dockerfile +16 -0
  45. package/td/modules/td_server/README.md +49 -0
  46. package/td/modules/td_server/git_push.sh +57 -0
  47. package/td/modules/td_server/openapi_server/__init__.py +0 -0
  48. package/td/modules/td_server/openapi_server/__main__.py +19 -0
  49. package/td/modules/td_server/openapi_server/controllers/__init__.py +0 -0
  50. package/td/modules/td_server/openapi_server/controllers/default_controller.py +160 -0
  51. package/td/modules/td_server/openapi_server/controllers/security_controller.py +2 -0
  52. package/td/modules/td_server/openapi_server/encoder.py +19 -0
  53. package/td/modules/td_server/openapi_server/models/__init__.py +33 -0
  54. package/td/modules/td_server/openapi_server/models/base_model.py +68 -0
  55. package/td/modules/td_server/openapi_server/models/create_node200_response.py +125 -0
  56. package/td/modules/td_server/openapi_server/models/create_node200_response_data.py +63 -0
  57. package/td/modules/td_server/openapi_server/models/create_node_request.py +123 -0
  58. package/td/modules/td_server/openapi_server/models/delete_node200_response.py +125 -0
  59. package/td/modules/td_server/openapi_server/models/delete_node200_response_data.py +91 -0
  60. package/td/modules/td_server/openapi_server/models/exec_node_method200_response.py +125 -0
  61. package/td/modules/td_server/openapi_server/models/exec_node_method200_response_data.py +65 -0
  62. package/td/modules/td_server/openapi_server/models/exec_node_method_request.py +153 -0
  63. package/td/modules/td_server/openapi_server/models/exec_node_method_request_args_inner.py +34 -0
  64. package/td/modules/td_server/openapi_server/models/exec_python_script200_response.py +125 -0
  65. package/td/modules/td_server/openapi_server/models/exec_python_script200_response_data.py +65 -0
  66. package/td/modules/td_server/openapi_server/models/exec_python_script200_response_data_result.py +63 -0
  67. package/td/modules/td_server/openapi_server/models/exec_python_script_request.py +65 -0
  68. package/td/modules/td_server/openapi_server/models/get_node_detail200_response.py +125 -0
  69. package/td/modules/td_server/openapi_server/models/get_nodes200_response.py +125 -0
  70. package/td/modules/td_server/openapi_server/models/get_nodes200_response_data.py +65 -0
  71. package/td/modules/td_server/openapi_server/models/get_td_info200_response.py +125 -0
  72. package/td/modules/td_server/openapi_server/models/get_td_info200_response_data.py +155 -0
  73. package/td/modules/td_server/openapi_server/models/get_td_python_class_details200_response.py +125 -0
  74. package/td/modules/td_server/openapi_server/models/get_td_python_classes200_response.py +125 -0
  75. package/td/modules/td_server/openapi_server/models/get_td_python_classes200_response_data.py +63 -0
  76. package/td/modules/td_server/openapi_server/models/td_node.py +175 -0
  77. package/td/modules/td_server/openapi_server/models/td_node_family_type.py +44 -0
  78. package/td/modules/td_server/openapi_server/models/td_python_class_details.py +191 -0
  79. package/td/modules/td_server/openapi_server/models/td_python_class_info.py +127 -0
  80. package/td/modules/td_server/openapi_server/models/td_python_method_info.py +121 -0
  81. package/td/modules/td_server/openapi_server/models/td_python_property_info.py +123 -0
  82. package/td/modules/td_server/openapi_server/models/update_node200_response.py +125 -0
  83. package/td/modules/td_server/openapi_server/models/update_node200_response_data.py +149 -0
  84. package/td/modules/td_server/openapi_server/models/update_node200_response_data_failed_inner.py +91 -0
  85. package/td/modules/td_server/openapi_server/models/update_node_request.py +93 -0
  86. package/td/modules/td_server/openapi_server/openapi/openapi.yaml +966 -0
  87. package/td/modules/td_server/openapi_server/test/__init__.py +16 -0
  88. package/td/modules/td_server/openapi_server/test/test_default_controller.py +200 -0
  89. package/td/modules/td_server/openapi_server/typing_utils.py +30 -0
  90. package/td/modules/td_server/openapi_server/util.py +147 -0
  91. package/td/modules/td_server/requirements.txt +13 -0
  92. package/td/modules/td_server/setup.py +37 -0
  93. package/td/modules/td_server/test-requirements.txt +4 -0
  94. package/td/modules/td_server/tox.ini +11 -0
  95. package/td/modules/utils/config.py +7 -0
  96. package/td/modules/utils/error_handling.py +104 -0
  97. package/td/modules/utils/logging.py +23 -0
  98. package/td/modules/utils/result.py +40 -0
  99. package/td/modules/utils/serialization.py +57 -0
  100. package/td/modules/utils/types.py +33 -0
  101. package/td/modules/utils/utils_logging.py +60 -0
  102. package/td/templates/mcp/api_controller_handlers.mustache +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 sadao komaki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ja.md ADDED
@@ -0,0 +1,211 @@
1
+ # TouchDesigner MCP
2
+
3
+ TouchDesignerのためのMCP(Model Context Protocol) サーバー実装です。AIエージェントがTouchDesignerプロジェクトを制御・操作できるようになることを目指しています。
4
+
5
+ ## 概要
6
+
7
+ ![スクリーンショット 2025-04-14 21 45 47](https://github.com/user-attachments/assets/b7130ebe-406c-4e05-9efc-5d493eb800cb)
8
+
9
+ TouchDesigner MCPは、AIモデルとTouchDesigner WebServer DAT 間のブリッジとして機能し、AIエージェントが以下のことが可能になります
10
+ - ノードの作成、変更、削除
11
+ - ノードプロパティやプロジェクト構造の照会
12
+ - PythonスクリプトによるTouchDesignerのプログラム的制御
13
+
14
+ ## 前提条件
15
+
16
+ - Node.js(最新のLTSバージョンを推奨)
17
+ - TouchDesigner(最新の安定版を推奨)
18
+ - Docker(Pythonサーバーコードの生成に必要)
19
+
20
+ ## MCPサーバーコードのビルド
21
+
22
+ 1. リポジトリのクローン
23
+ ```bash
24
+ git clone https://github.com/8beeeaaat/touchdesigner-mcp.git
25
+ ```
26
+
27
+ 2. 依存パッケージのインストール
28
+ ```bash
29
+ cd touchdesigner-mcp
30
+ npm install
31
+ ```
32
+ 3. 環境設定ファイルの設置とビルド
33
+ ```
34
+ # テンプレートをコピーし、必要に応じて TD_WEB_SERVER_URL を調整してください
35
+ cp dotenv .env
36
+
37
+ # プロジェクトのビルド(APIクライアント/サーバー向けスキーマを生成し、MCPリソースをコンパイルします)
38
+ # このコマンドを実行する前にDockerデーモンが実行されていることを確認してください
39
+ npm run build
40
+ ```
41
+
42
+ ## 使い方
43
+
44
+ ### TouchDesignerのセットアップ
45
+
46
+ 1. **コード生成:**
47
+ [MCPサーバーコードのビルド](#MCPサーバーコードのビルド) を参考に、プロジェクトルートで `npm run build` を実行します。これにより以下のコードが生成されます。
48
+ - MCPサーバコード
49
+ - TouchDesigner WebSever DAT向けのAPIサーバーコード
50
+ 2. **TouchDesigner に MCPサーバー向けWebServerをインポートする:**
51
+ TouchDesignerを起動し、`td/mcp_webserver_base.tox` コンポーネントをTouchDesignerプロジェクト直下にimportします。
52
+ tox のimport により `td/import_modules.py` スクリプトが動作し、APIサーバのコントローラなどのモジュールがロードされます。
53
+
54
+ 3. **APIサーバの動作確認:**
55
+ `td/modules` ディレクトリ内のPythonモジュールが `mcp_webserver_base` コンポーネントからアクセス可能であることを確認します。
56
+ `npm run test` を実行することでMCPサーバーコードのユニットテストと TouchDesigner への結合テストが実行されます。
57
+ TOuchDesigner のメニューから Textportを起動すると通信のログを確認することができます。
58
+
59
+ *TIPS*
60
+ `mcp_webserver_base.tox` には、MCPサーバーとTouchDesignerを連携させるように設定された WebServer DAT が含まれています。
61
+ このDATがActiveであり、`.env` ファイルの `TD_WEB_SERVER_URL` で指定されたポートで実行されていることを確認してください。(デフォルト: `9981`)
62
+ 実行するポートを任意のものに変更したい場合は、以下の手順に従ってください。
63
+ 1. `.env` ファイルの `TD_WEB_SERVER_PORT` を変更
64
+ 2. `npm run build` を再実行
65
+ 3. mcp_webserver_base (WebServer DAT) のポートを変更し、WebServer DATをRestart
66
+
67
+ ### MCP対応 AIエージェントとの接続
68
+
69
+ TouchDesignerが起動した状態で、AIエージェント(Cursor, Claude Desktop, VSCode CopilotChatなど)をMCPサーバーに接続するように設定します。
70
+
71
+ ```json
72
+ // 設定例(例:VS Code settings.json の Copilot Chat 用)
73
+ "github.copilot.advanced": {
74
+ "touchdesigner": {
75
+ "command": "node",
76
+ "args": [
77
+ "/path/to/your/touchdesigner-mcp/dist/index.js", // <-- npm run buildによって生成された dist/index.js への絶対パスに置き換えてください
78
+ "--stdio"
79
+ ],
80
+ "transportType": "stdio"
81
+ }
82
+ }
83
+ ```
84
+
85
+ TouchDesigner で APIサーバーが実行されていれば、エージェントは提供された TouchDesigner ツールを通じてTouchDesignerを使用できます。
86
+
87
+ ## セットアップ後のプロジェクト構造概要
88
+
89
+ ```
90
+ ├── src/ # MCPサーバー ソースコード
91
+ │ ├── api/ # TD WebServerに対するOpenAPI仕様
92
+ │ ├── core/ # コアユーティリティ (ロガー, エラーハンドリング)
93
+ │ ├── features/ # MCP機能実装
94
+ │ │ ├── prompts/ # プロンプトハンドラ
95
+ │ │ ├── resources/ # リソースハンドラ
96
+ │ │ └── tools/ # ツールハンドラ (例: tdTools.ts)
97
+ │ ├── gen/ # OpenAPIスキーマから生成されたMCPサーバー向けコード
98
+ │ ├── server/ # MCPサーバーロジック (接続, メインサーバークラス)
99
+ │ ├── tdClient/ # TD接続API用クライアント
100
+ │ ├── index.ts # Node.jsサーバーのメインエントリーポイント
101
+ │ └── ...
102
+ ├── td/ # TouchDesigner関連ファイル
103
+ │ ├── modules/ # TouchDesigner用Pythonモジュール
104
+ │ │ ├── mcp/ # TD内でMCPからのリクエストを処理するコアロジック
105
+ │ │ │ ├── controllers/ # APIリクエストコントローラ (api_controller.py, generated_handlers.py)
106
+ │ │ │ └── services/ # ビジネスロジック (api_service.py)
107
+ │ │ ├── td_server/ # OpenAPIスキーマから生成されたPythonモデルコード
108
+ │ │ └── utils/ # 共有Pythonユーティリティ
109
+ │ ├── templates/ # Pythonコード生成用Mustacheテンプレート
110
+ │ ├── genHandlers.js # generated_handlers.py 生成用のNode.jsスクリプト
111
+ │ ├── import_modules.py # TDへ APIサーバ関連モジュールをインポートするヘルパースクリプト
112
+ │ └── mcp_webserver_base.tox # メインTouchDesignerコンポーネント
113
+ ├── tests/ # テストコード
114
+ │ ├── integration/
115
+ │ └── unit/
116
+ ├── .env # ローカル環境変数 (git無視)
117
+ ├── dotenv # .env用テンプレート
118
+ └── orval.config.ts # Orval 設定 (TSクライアント生成)
119
+ ```
120
+
121
+ ## MCPサーバーの機能
122
+
123
+ このサーバーは、Model Context Protocol (MCP) を通じてTouchDesigner への操作、および各種実装ドキュメントへの参照を可能にします。
124
+
125
+ ### ツール (Tools)
126
+
127
+ ツールは、AIエージェントがTouchDesignerでアクションを実行できるようにします。
128
+
129
+ | ツール名 | 説明 |
130
+ | :-------------------------- | :--------------------------------------------- |
131
+ | `create_td_node` | 新しいノードを作成します。 |
132
+ | `delete_td_node` | 既存のノードを削除します。 |
133
+ | `exec_node_method`| ノードに対しPythonメソッドを呼び出します。 |
134
+ | `execute_python_script` | TD内で任意のPythonスクリプトを実行します。 |
135
+ | `get_td_class_details` | TD Pythonクラス/モジュールの詳細情報を取得します。 |
136
+ | `get_td_classes` | TouchDesigner Pythonクラスのリストを取得します。 |
137
+ | `get_td_info` | TDサーバー環境に関する情報を取得します。 |
138
+ | `get_td_node_parameters` | 特定ノードのパラメータを取得します。 |
139
+ | `get_td_nodes` | 親パス内のノードを取得します(オプションでフィルタリング)。 |
140
+ | `update_td_node_parameters` | 特定ノードのパラメータを更新します。 |
141
+
142
+ ### プロンプト (Prompts)
143
+
144
+ プロンプトは、AIエージェントがTouchDesignerで特定のアクションを実行するための指示を提供します。
145
+
146
+ | プロンプト名 | 説明 |
147
+ | :-------------------------- | :--------------------------------------------- |
148
+ | `Search node` | ノードをファジー検索し、指定されたノード名、ファミリー、タイプに基づいて情報を取得します。 |
149
+ | `Node connection` | TouchDesigner内でノード同士を接続するための指示を提供します。 |
150
+ | `Check node errors` | 指定されたノードのエラーをチェックします。子ノードがあれば再帰的にチェックします。 |
151
+
152
+ ### リソース (Resources)
153
+
154
+ 未実装
155
+
156
+ ## 開発
157
+
158
+ ### 開発環境のセットアップ
159
+
160
+ ```bash
161
+ # 依存関係のインストール
162
+ npm install
163
+
164
+ # リンターと型チェッカーの実行
165
+ npm run lint
166
+
167
+ # テストの実行
168
+ npm test
169
+
170
+ # デバッグ用にMCP Inspectorを使用してサーバーを起動
171
+ npm run dev
172
+ ```
173
+
174
+ ### APIコード生成ワークフロー
175
+
176
+ このプロジェクトでは、OpenAPIによるコード生成ツール ( Orval / openapi-generator-cli )を使用しています:
177
+
178
+ **API定義:** Node.js MCPサーバーとTouchDesigner内で実行されるPythonサーバー間のAPI規約は `src/api/index.yml` で定義されます。
179
+
180
+ 1. **Pythonサーバー生成 (`npm run gen:webserver`):**
181
+ * Docker経由で `openapi-generator-cli` を使用します。
182
+ * `src/api/index.yml` を読み取ります。
183
+ * API定義に基づいてPythonサーバーのスケルトン (`td/modules/td_server/`) を生成します。このコードはWebServer DATを介してTouchDesigner内で実行されます。
184
+ * **Dockerがインストールされ、実行されている必要があります。**
185
+ 2. **Pythonハンドラ生成 (`npm run gen:handlers`):**
186
+ * カスタムNode.jsスクリプト (`td/genHandlers.js`) とMustacheテンプレート (`td/templates/`) を使用します。
187
+ * 生成されたPythonサーバーコードまたはOpenAPI仕様を読み取ります。
188
+ * `td/modules/mcp/services/api_service.py` にあるビジネスロジックに接続するハンドラ実装 (`td/modules/mcp/controllers/generated_handlers.py`) を生成します。
189
+ 3. **TypeScriptクライアント生成 (`npm run gen:mcp`):**
190
+ * `Orval` を使用し `openapi-generator-cli` がバンドルしたスキーマYAMLからAPIクライアントコードとToolの検証に用いるZodスキーマを生成します。
191
+ * Node.jsサーバーが WebServerDAT にリクエストを行うために使用する、型付けされたTypeScriptクライアント (`src/tdClient/`) を生成します。
192
+
193
+ ビルドプロセス (`npm run build`) は、必要なすべての生成ステップ (`npm run gen`) を実行し、その後にTypeScriptコンパイル (`tsc`) を行います。
194
+
195
+ ## 貢献
196
+
197
+ 貢献は歓迎します!貢献方法は以下の通りです:
198
+
199
+ 1. リポジトリをフォーク
200
+ 2. 機能ブランチを作成(`git checkout -b feature/amazing-feature`)
201
+ 3. 変更を加える
202
+ 4. テストを追加し、すべてが正常に動作することを確認(`npm test`)
203
+ 5. 変更をコミット(`git commit -m 'Add some amazing feature'`)
204
+ 6. ブランチにプッシュ(`git push origin feature/amazing-feature`)
205
+ 7. プルリクエストを開く
206
+
207
+ プロジェクトのコーディング標準に従い、適切なテストを含めてください。
208
+
209
+ ## ライセンス
210
+
211
+ MIT
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ # TouchDesigner MCP
2
+
3
+ TouchDesigner MCP is an implementation of the Model Context Protocol (MCP) server for TouchDesigner, aiming to enable AI agents to control and interact with TouchDesigner projects.
4
+
5
+ ## Overview
6
+
7
+ ![スクリーンショット 2025-04-14 21 45 47](https://github.com/user-attachments/assets/b7130ebe-406c-4e05-9efc-5d493eb800cb)
8
+
9
+ TouchDesigner MCP acts as a bridge between AI models and the TouchDesigner WebServer DAT, allowing AI agents to:
10
+ - Create, modify, and delete nodes
11
+ - Query node properties and project structure
12
+ - Programmatically control TouchDesigner using Python scripts
13
+
14
+ ## Prerequisites
15
+
16
+ - Node.js (latest LTS version recommended)
17
+ - TouchDesigner (latest stable version recommended)
18
+ - Docker (Required for generating Python server code)
19
+
20
+ ## Building the MCP Server Code
21
+
22
+ 1. Clone the repository:
23
+ ```bash
24
+ git clone https://github.com/8beeeaaat/touchdesigner-mcp.git
25
+ ```
26
+
27
+ 2. Install dependencies:
28
+ ```bash
29
+ cd touchdesigner-mcp
30
+ npm install
31
+ ```
32
+
33
+ 3. Set up environment configuration and build:
34
+ ```bash
35
+ # Copy the template and adjust TD_WEB_SERVER_URL if needed
36
+ cp dotenv .env
37
+
38
+ # Build the project (Generates API clients/servers and compiles MCP resources)
39
+ # Ensure Docker daemon is running before executing this command
40
+ npm run build
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ### Setting Up TouchDesigner
46
+
47
+ 1. **Generate Code:**
48
+ Refer to [Building the MCP Server Code](#building-the-mcp-server-code) and run `npm run build` in the project root. This generates:
49
+ - MCP server code
50
+ - API server code for the TouchDesigner WebServer DAT
51
+
52
+ 2. **Import MCP WebServer into TouchDesigner:**
53
+ Launch TouchDesigner and import the `td/mcp_webserver_base.tox` component into your TouchDesigner project. The import triggers the `td/import_modules.py` script, which loads modules such as API server controllers.
54
+
55
+ 3. **Verify API Server:**
56
+ Ensure that the Python modules in the `td/modules` directory are accessible from the `mcp_webserver_base` component. Run `npm run test` to execute unit tests for the MCP server code and integration tests with TouchDesigner. You can view communication logs by opening the Textport from the TouchDesigner menu.
57
+
58
+ *TIPS*
59
+ The `mcp_webserver_base.tox` includes a WebServer DAT configured to integrate the MCP server with TouchDesigner. Ensure this DAT is active and running on the port specified in the `.env` file's `TD_WEB_SERVER_URL` (default: `9981`). To change the port:
60
+ 1. Update `TD_WEB_SERVER_PORT` in the `.env` file.
61
+ 2. Rebuild the project with `npm run build`.
62
+ 3. Update the port in the WebServer DAT and restart it.
63
+
64
+ ### Connecting to an MCP-Compatible AI Agent
65
+
66
+ With TouchDesigner running, configure an AI agent (e.g., Cursor, Claude Desktop, VSCode CopilotChat) to connect to the MCP server.
67
+
68
+ ```json
69
+ // Example configuration (e.g., in VS Code settings.json for Copilot Chat)
70
+ "github.copilot.advanced": {
71
+ "touchdesigner": {
72
+ "command": "node",
73
+ "args": [
74
+ "/path/to/your/touchdesigner-mcp/dist/index.js", // <-- Replace with the absolute path generated by npm run build
75
+ "--stdio"
76
+ ],
77
+ "transportType": "stdio"
78
+ }
79
+ }
80
+ ```
81
+
82
+ Once the API server is running in TouchDesigner, the agent can use the provided TouchDesigner tools.
83
+
84
+ ## Project Structure Overview
85
+
86
+ ```
87
+ ├── src/ # MCP server source code
88
+ │ ├── api/ # OpenAPI specification for TD WebServer
89
+ │ ├── core/ # Core utilities (logger, error handling)
90
+ │ ├── features/ # MCP feature implementations
91
+ │ │ ├── prompts/ # Prompt handlers
92
+ │ │ ├── resources/ # Resource handlers
93
+ │ │ └── tools/ # Tool handlers (e.g., tdTools.ts)
94
+ │ ├── gen/ # Code generated from OpenAPI schema for MCP server
95
+ │ ├── server/ # MCP server logic (connections, main server class)
96
+ │ ├── tdClient/ # Client for TD connection API
97
+ │ ├── index.ts # Main entry point for the Node.js server
98
+ │ └── ...
99
+ ├── td/ # TouchDesigner-related files
100
+ │ ├── modules/ # Python modules for TouchDesigner
101
+ │ │ ├── mcp/ # Core logic for handling MCP requests in TD
102
+ │ │ │ ├── controllers/ # API request controllers (api_controller.py, generated_handlers.py)
103
+ │ │ │ └── services/ # Business logic (api_service.py)
104
+ │ │ ├── td_server/ # Python model code generated from OpenAPI schema
105
+ │ │ └── utils/ # Shared Python utilities
106
+ │ ├── templates/ # Mustache templates for Python code generation
107
+ │ ├── genHandlers.js # Node.js script for generating Python handlers
108
+ │ ├── import_modules.py # Helper script for importing API server modules into TD
109
+ │ └── mcp_webserver_base.tox # Main TouchDesigner component
110
+ ├── tests/ # Test code
111
+ │ ├── integration/
112
+ │ └── unit/
113
+ ├── .env # Local environment variables (gitignored)
114
+ ├── dotenv # Template for .env
115
+ └── orval.config.ts # Orval configuration (TS client generation)
116
+ ```
117
+
118
+ ## MCP Server Features
119
+
120
+ This server enables operations on TouchDesigner via the Model Context Protocol (MCP) and provides access to various tools.
121
+
122
+ ### Tools
123
+
124
+ | Tool Name | Description |
125
+ | :-------------------------- | :--------------------------------------------------- |
126
+ | `create_td_node` | Creates a new node. |
127
+ | `delete_td_node` | Deletes an existing node. |
128
+ | `exec_node_method` | Calls a Python method on a node. |
129
+ | `execute_python_script` | Executes an arbitrary Python script in TD. |
130
+ | `get_td_class_details` | Retrieves details of TD Python classes/modules. |
131
+ | `get_td_classes` | Lists TouchDesigner Python classes. |
132
+ | `get_td_info` | Retrieves information about the TD server environment. |
133
+ | `get_td_node_parameters` | Retrieves parameters of a specific node. |
134
+ | `get_td_nodes` | Retrieves nodes within a parent path (optional filtering). |
135
+ | `update_td_node_parameters` | Updates parameters of a specific node. |
136
+
137
+ ### Prompts
138
+
139
+ Prompts allow AI agents to perform specific actions in TouchDesigner.
140
+
141
+ | Prompt Name | Description |
142
+ | :-------------------------- | :--------------------------------------------------- |
143
+ | `Search node` | Performs a fuzzy search for nodes based on name, family, or type. |
144
+ | `Node connection` | Provides instructions for connecting nodes in TouchDesigner. |
145
+ | `Check node errors` | Checks for errors in specified nodes, recursively if child nodes exist. |
146
+
147
+ ### Resources
148
+
149
+ Not implemented.
150
+
151
+ ## Development
152
+
153
+ ### Setting Up the Development Environment
154
+
155
+ ```bash
156
+ # Install dependencies
157
+ npm install
158
+
159
+ # Run linters and type checkers
160
+ npm run lint
161
+
162
+ # Run tests
163
+ npm test
164
+
165
+ # Start the server with MCP Inspector for debugging
166
+ npm run dev
167
+ ```
168
+
169
+ ### API Code Generation Workflow
170
+
171
+ This project uses OpenAPI-based code generation tools (Orval / openapi-generator-cli):
172
+
173
+ **API Definition:** The API contract between the Node.js MCP server and the Python server running in TouchDesigner is defined in `src/api/index.yml`.
174
+
175
+ 1. **Python Server Generation (`npm run gen:webserver`):**
176
+ * Uses Docker to run `openapi-generator-cli`.
177
+ * Reads `src/api/index.yml`.
178
+ * Generates Python server skeleton (`td/modules/td_server/`) for the WebServer DAT in TouchDesigner.
179
+ * **Requires Docker to be installed and running.**
180
+ 2. **Python Handler Generation (`npm run gen:handlers`):**
181
+ * Uses a custom Node.js script (`td/genHandlers.js`) and Mustache templates (`td/templates/`).
182
+ * Generates handler implementations (`td/modules/mcp/controllers/generated_handlers.py`) that connect to business logic in `td/modules/mcp/services/api_service.py`.
183
+ 3. **TypeScript Client Generation (`npm run gen:mcp`):**
184
+ * Uses `Orval` to generate a TypeScript client (`src/tdClient/`) for the Node.js server to communicate with the Python server.
185
+
186
+ The build process (`npm run build`) executes all generation steps (`npm run gen`) and compiles TypeScript (`tsc`).
187
+
188
+ ## Contributing
189
+
190
+ Contributions are welcome! Follow these steps:
191
+
192
+ 1. Fork the repository.
193
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`).
194
+ 3. Make your changes.
195
+ 4. Add tests and ensure everything works (`npm test`).
196
+ 5. Commit your changes (`git commit -m 'Add some amazing feature'`).
197
+ 6. Push to the branch (`git push origin feature/amazing-feature`).
198
+ 7. Open a Pull Request.
199
+
200
+ Ensure your code follows the project's coding standards and includes appropriate tests.
201
+
202
+ ## License
203
+
204
+ MIT
@@ -0,0 +1,18 @@
1
+ import Axios from "axios";
2
+ const API_BASE_URL = process.env.API_BASE_URL || "http://localhost:9981";
3
+ export const AXIOS_INSTANCE = Axios.create({
4
+ baseURL: API_BASE_URL,
5
+ });
6
+ export const customInstance = (config, options) => {
7
+ const source = Axios.CancelToken.source();
8
+ const promise = AXIOS_INSTANCE({
9
+ ...config,
10
+ ...options,
11
+ cancelToken: source.token,
12
+ }).then(({ data }) => data);
13
+ // @ts-ignore
14
+ promise.cancel = () => {
15
+ source.cancel("Query was cancelled");
16
+ };
17
+ return promise;
18
+ };
package/dist/cli.js ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ import { resolve } from "node:path";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { config } from "dotenv";
5
+ import { TouchDesignerServer } from "./server/touchDesignerServer.js";
6
+ config({ path: resolve(process.cwd(), ".env") });
7
+ /**
8
+ * Start TouchDesigner MCP server
9
+ */
10
+ export async function startServer() {
11
+ const isStdioMode = process.env.NODE_ENV === "cli" || process.argv.includes("--stdio");
12
+ try {
13
+ const server = new TouchDesignerServer();
14
+ if (isStdioMode) {
15
+ const transport = new StdioServerTransport();
16
+ const result = await server.connect(transport);
17
+ if (!result.success) {
18
+ throw new Error(`Failed to connect: ${result.error.message}`);
19
+ }
20
+ }
21
+ else {
22
+ throw new Error("Sorry, this server is not yet available in the browser. Please use the CLI mode.");
23
+ }
24
+ }
25
+ catch (error) {
26
+ const errorMessage = error instanceof Error ? error.message : String(error);
27
+ console.error(`Failed to initialize server: ${errorMessage}`);
28
+ process.exit(1);
29
+ }
30
+ }
31
+ if (process.argv[1]) {
32
+ startServer().catch((error) => {
33
+ console.error("Failed to start server:", error);
34
+ process.exit(1);
35
+ });
36
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Reference URLs for TouchDesigner Python documentation
3
+ */
4
+ export const TD_PYTHON_CLASS_REFERENCE_BASE_URL = "https://docs.derivative.ca";
5
+ export const TD_PYTHON_CLASS_REFERENCE_INDEX_URL = `${TD_PYTHON_CLASS_REFERENCE_BASE_URL}/Python_Classes_and_Modules`;
6
+ /**
7
+ * Reference Tool Names for TouchDesigner MCP
8
+ */
9
+ export const TOOL_NAMES = {
10
+ CREATE_TD_NODE: "create_td_node",
11
+ DELETE_TD_NODE: "delete_td_node",
12
+ EXECUTE_PYTHON_SCRIPT: "execute_python_script",
13
+ EXECUTE_NODE_METHOD: "exec_node_method",
14
+ GET_TD_INFO: "get_td_info",
15
+ GET_TD_CLASS_DETAILS: "get_td_class_details",
16
+ GET_TD_CLASSES: "get_td_classes",
17
+ GET_TD_NODE_PARAMETERS: "get_td_node_parameters",
18
+ GET_TD_NODES: "get_td_nodes",
19
+ UPDATE_TD_NODE_PARAMETERS: "update_td_node_parameters",
20
+ };
21
+ export const REFERENCE_COMMENT = `Check reference resources: ${TD_PYTHON_CLASS_REFERENCE_INDEX_URL}.`;
22
+ export const PROMPT_NAMES = {
23
+ SEARCH_NODE: "Search node",
24
+ CHECK_NODE_ERRORS: "Check node errors",
25
+ NODE_CONNECTION: "Node connection",
26
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Handles API errors consistently across the application
3
+ */
4
+ export function handleToolError(error, logger, toolName, referenceComment) {
5
+ const formattedError = error instanceof Error
6
+ ? error
7
+ : new Error(error === null ? "Null error received" : String(error));
8
+ logger.error(toolName, formattedError);
9
+ const errorMessage = `${toolName}: ${formattedError}${referenceComment ? `. ${referenceComment}` : ""}`;
10
+ return {
11
+ isError: true,
12
+ content: [
13
+ {
14
+ type: "text",
15
+ text: errorMessage,
16
+ },
17
+ ],
18
+ };
19
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * MCP compatible logger implementation
3
+ * Handles "Not connected" errors gracefully
4
+ */
5
+ export class McpLogger {
6
+ server;
7
+ constructor(server) {
8
+ this.server = server;
9
+ }
10
+ // biome-ignore lint/suspicious/noExplicitAny: logging accepts any type
11
+ log(...args) {
12
+ this.sendLog("info", args);
13
+ }
14
+ // biome-ignore lint/suspicious/noExplicitAny: logging accepts any type
15
+ debug(...args) {
16
+ this.sendLog("debug", args);
17
+ }
18
+ // biome-ignore lint/suspicious/noExplicitAny: logging accepts any type
19
+ warn(...args) {
20
+ this.sendLog("warning", args);
21
+ }
22
+ // biome-ignore lint/suspicious/noExplicitAny: logging accepts any type
23
+ error(...args) {
24
+ this.sendLog("error", args);
25
+ }
26
+ sendLog(level,
27
+ // biome-ignore lint/suspicious/noExplicitAny: logging accepts any type
28
+ args) {
29
+ for (const arg of args) {
30
+ try {
31
+ this.server.server.sendLoggingMessage({
32
+ level,
33
+ data: arg,
34
+ });
35
+ }
36
+ catch (error) {
37
+ if (error instanceof Error && error.message === "Not connected") {
38
+ return;
39
+ }
40
+ console.error(`Failed to send log to MCP server: ${error instanceof Error ? error.message : String(error)}`);
41
+ console[level === "warning" ? "warn" : level]?.(arg);
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Creates a success result with the provided data
3
+ */
4
+ export function createSuccessResult(data) {
5
+ return { success: true, data };
6
+ }
7
+ /**
8
+ * Creates an error result with the provided error
9
+ */
10
+ export function createErrorResult(error) {
11
+ return { success: false, error };
12
+ }