touchdesigner-mcp-server 0.2.13 → 0.4.0-alpha.0
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.
- package/README.ja.md +70 -58
- package/README.md +69 -60
- package/dist/cli.js +6 -2
- package/dist/features/tools/handlers/tdTools.js +7 -2
- package/dist/gen/endpoints/TouchDesignerAPI.js +1 -1
- package/dist/gen/mcp/touchDesignerAPI.zod.js +4 -2
- package/dist/server/connectionManager.js +1 -1
- package/dist/server/touchDesignerServer.js +1 -1
- package/package.json +11 -3
- package/td/modules/mcp/controllers/api_controller.py +7 -2
- package/td/modules/mcp/services/api_service.py +24 -4
- package/td/modules/td_server/openapi_server/controllers/default_controller.py +3 -1
- package/td/modules/td_server/openapi_server/openapi/openapi.yaml +10 -1
- package/td/modules/td_server/openapi_server/test/test_default_controller.py +2 -1
- package/src/index.ts +0 -6
package/README.ja.md
CHANGED
|
@@ -15,9 +15,41 @@ TouchDesigner MCPは、AIモデルとTouchDesigner WebServer DAT 間のブリッ
|
|
|
15
15
|
|
|
16
16
|
## 利用方法
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
<details>
|
|
19
|
+
<summary>方法1: npx を利用する(クイックスタート)</summary>
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
*Node.jsがインストールされていることが前提となります*
|
|
22
|
+
|
|
23
|
+
##### 1. TouchDesigner プロジェクトにMCP連携用のAPIサーバーを設置
|
|
24
|
+
|
|
25
|
+
npxを使用する場合、TouchDesignerコンポーネントを別途ダウンロードする必要があります:
|
|
26
|
+
1. [リリースページ](https://github.com/8beeeaaat/touchdesigner-mcp/releases)から `touchdesigner-mcp-td.zip` をダウンロード
|
|
27
|
+
2. zipファイルを展開して `td` ディレクトリを取得
|
|
28
|
+
3. 展開したファイルから `mcp_webserver_base.tox` を操作したいTouchDesignerプロジェクト直下にimportします。
|
|
29
|
+
例: `/project1/mcp_webserver_base` となるように配置
|
|
30
|
+
|
|
31
|
+
**⚠️ 重要:** `td` ディレクトリの構造は展開した状態を正確に保持する必要があります。`mcp_webserver_base.tox` コンポーネントは `modules/` ディレクトリやその他のファイルへの相対パスを参照しています。展開した `td` ディレクトリ内のファイルを移動したり再編成したりしないでください。
|
|
32
|
+
|
|
33
|
+
##### 2. AIエージェントの設定:
|
|
34
|
+
|
|
35
|
+
*例 Claude Desktop*
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"touchdesigner": {
|
|
40
|
+
"command": "npx",
|
|
41
|
+
"args": [
|
|
42
|
+
"touchdesigner-mcp-server",
|
|
43
|
+
"--stdio"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
</details>
|
|
50
|
+
|
|
51
|
+
<details>
|
|
52
|
+
<summary>方法2: Dockerイメージを利用</summary>
|
|
21
53
|
|
|
22
54
|
[](https://www.youtube.com/watch?v=BRWoIEVb0TU)
|
|
23
55
|
|
|
@@ -70,7 +102,7 @@ docker-compose up -d
|
|
|
70
102
|
"-i",
|
|
71
103
|
"touchdesigner-mcp-server",
|
|
72
104
|
"node",
|
|
73
|
-
"dist/
|
|
105
|
+
"dist/cli.js",
|
|
74
106
|
"--stdio"
|
|
75
107
|
]
|
|
76
108
|
}
|
|
@@ -79,58 +111,31 @@ docker-compose up -d
|
|
|
79
111
|
```
|
|
80
112
|
|
|
81
113
|
*Windows環境では C:\\ の様にドライブレターを含めてください。 例. `C:\\path\\to\\your\\touchdesigner-mcp\\docker-compose.yml`*
|
|
114
|
+
</details>
|
|
82
115
|
|
|
83
116
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Node.jsから直接ビルド済みのjsを利用する場合は、以下の手順に従います:
|
|
87
|
-
|
|
88
|
-
[](https://www.youtube.com/watch?v=jFaUP1fYum0)
|
|
89
|
-
|
|
90
|
-
##### 1. パッケージのインストール
|
|
91
|
-
```bash
|
|
92
|
-
mkdir some && cd ./some # 必要に応じて任意のディレクトリを作成
|
|
93
|
-
npm install touchdesigner-mcp-server
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
##### 2. TouchDesigner プロジェクトにMCP連携用のAPIサーバーを設置
|
|
97
|
-
|
|
98
|
-
TouchDesignerを起動し、`some/node_modules/touchdesigner-mcp-server/td/mcp_webserver_base.tox` コンポーネントを操作したいTouchDesignerプロジェクト直下にimportします。
|
|
99
|
-
例: `/project1/mcp_webserver_base` となるように配置
|
|
100
|
-
|
|
101
|
-
tox のimport により `some/node_modules/touchdesigner-mcp-server/td/import_modules.py` スクリプトが動作し、APIサーバのコントローラなどのモジュールがロードされます。
|
|
102
|
-
|
|
103
|
-

|
|
117
|
+
## 接続確認
|
|
104
118
|
|
|
105
|
-
|
|
119
|
+
MCPサーバーが認識されていればセットアップは完了です。
|
|
120
|
+
認識されない場合はAIエージェントを再起動するなどしてください。
|
|
121
|
+
起動時にエラーが表示される場合はTouchDesignerを先に起動してから再度エージェントを起動してください。
|
|
122
|
+
TouchDesigner で APIサーバーが実行されていれば、エージェントは提供された ツール等を通じてTouchDesignerを使用できます。
|
|
106
123
|
|
|
107
|
-
|
|
124
|
+
### ディレクトリ構造要件
|
|
108
125
|
|
|
109
|
-
|
|
126
|
+
**重要:** どの方法(Docker、npx)を使用する場合でも、正確なディレクトリ構造を維持してください:
|
|
110
127
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
],
|
|
120
|
-
"command": "node"
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
128
|
+
```
|
|
129
|
+
td/
|
|
130
|
+
├── import_modules.py # モジュールローダースクリプト
|
|
131
|
+
├── mcp_webserver_base.tox # メインTouchDesignerコンポーネント
|
|
132
|
+
└── modules/ # Pythonモジュールディレクトリ
|
|
133
|
+
├── mcp/ # MCPコアロジック
|
|
134
|
+
├── utils/ # 共有ユーティリティ
|
|
135
|
+
└── td_server/ # 生成されたAPIサーバーコード
|
|
124
136
|
```
|
|
125
137
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
### 3. 接続確認
|
|
129
|
-
|
|
130
|
-
MCPサーバーが認識されていればセットアップは完了です。
|
|
131
|
-
認識されない場合はAIエージェントを再起動するなどしてください。
|
|
132
|
-
起動時にエラーが表示される場合はTouchDesignerを先に起動してから再度エージェントを起動してください。
|
|
133
|
-
TouchDesigner で APIサーバーが実行されていれば、エージェントは提供された ツール等を通じてTouchDesignerを使用できます。
|
|
138
|
+
`mcp_webserver_base.tox` コンポーネントは相対パスを使用してPythonモジュールを検索します。これらのファイルを移動したり再編成したりすると、TouchDesignerでインポートエラーが発生します。
|
|
134
139
|
|
|
135
140
|

|
|
136
141
|
|
|
@@ -172,21 +177,28 @@ TouchDesigner で APIサーバーが実行されていれば、エージェン
|
|
|
172
177
|
|
|
173
178
|
## 開発者向け
|
|
174
179
|
|
|
175
|
-
###
|
|
180
|
+
### 開発のクイックスタート
|
|
176
181
|
|
|
177
|
-
1.
|
|
178
|
-
|
|
179
|
-
|
|
182
|
+
1. **環境設定:**
|
|
183
|
+
```bash
|
|
184
|
+
cp dotenv .env
|
|
185
|
+
# .env ファイルの TD_WEB_SERVER_HOST, TD_WEB_SERVER_PORT を開発環境に合わせて変更
|
|
186
|
+
```
|
|
180
187
|
|
|
181
|
-
|
|
188
|
+
2. **プロジェクトをビルド:**
|
|
189
|
+
```bash
|
|
190
|
+
make build # Docker-based build(推奨)
|
|
191
|
+
# または
|
|
192
|
+
npm run build # Node.js-based build
|
|
193
|
+
```
|
|
182
194
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
195
|
+
3. **利用可能なコマンド:**
|
|
196
|
+
```bash
|
|
197
|
+
npm run test # ユニットテストと結合テストを実行
|
|
198
|
+
npm run dev # デバッグ用MCPインスペクターを起動
|
|
199
|
+
```
|
|
187
200
|
|
|
188
|
-
|
|
189
|
-
@modelcontextprotocol/inspector が起動し、各種機能をデバッグすることができます。
|
|
201
|
+
**注意:** コードを更新した場合は、MCPサーバーとTouchDesignerの両方を再起動して変更を反映してください。
|
|
190
202
|
|
|
191
203
|
### プロジェクト構造の概要
|
|
192
204
|
|
package/README.md
CHANGED
|
@@ -15,10 +15,41 @@ TouchDesigner MCP acts as a bridge between AI models and the TouchDesigner WebSe
|
|
|
15
15
|
|
|
16
16
|
## Usage
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
<details>
|
|
19
|
+
<summary>Method 1: Using npx (Quick Start)</summary>
|
|
20
|
+
|
|
21
|
+
*Requires Node.js to be installed*
|
|
22
|
+
|
|
23
|
+
#### 1. Install the API Server in Your TouchDesigner Project:
|
|
24
|
+
|
|
25
|
+
Since you're using npx, you'll need to download the TouchDesigner components separately:
|
|
26
|
+
1. Download `touchdesigner-mcp-td.zip` from the [releases page](https://github.com/8beeeaaat/touchdesigner-mcp/releases)
|
|
27
|
+
2. Extract the zip file to get the `td` directory
|
|
28
|
+
3. Import `mcp_webserver_base.tox` from the extracted files directly under the TouchDesigner project you want to control.
|
|
29
|
+
Example: Place it as `/project1/mcp_webserver_base`
|
|
30
|
+
|
|
31
|
+
**⚠️ Important:** The `td` directory structure must be preserved exactly as extracted. The `mcp_webserver_base.tox` component references relative paths to the `modules/` directory and other files. Do not move or reorganize files within the extracted `td` directory.
|
|
32
|
+
|
|
33
|
+
#### 2. Configure your AI agent:
|
|
34
|
+
|
|
35
|
+
*Example for Claude Desktop*
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"touchdesigner": {
|
|
40
|
+
"command": "npx",
|
|
41
|
+
"args": [
|
|
42
|
+
"touchdesigner-mcp-server",
|
|
43
|
+
"--stdio"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
</details>
|
|
19
50
|
|
|
20
51
|
<details>
|
|
21
|
-
<summary>Method
|
|
52
|
+
<summary>Method 2: Using Docker Image</summary>
|
|
22
53
|
|
|
23
54
|
[](https://www.youtube.com/watch?v=BRWoIEVb0TU)
|
|
24
55
|
|
|
@@ -71,7 +102,7 @@ TouchDesigner MCP acts as a bridge between AI models and the TouchDesigner WebSe
|
|
|
71
102
|
"-i",
|
|
72
103
|
"touchdesigner-mcp-server",
|
|
73
104
|
"node",
|
|
74
|
-
"dist/
|
|
105
|
+
"dist/cli.js",
|
|
75
106
|
"--stdio"
|
|
76
107
|
]
|
|
77
108
|
}
|
|
@@ -82,59 +113,30 @@ TouchDesigner MCP acts as a bridge between AI models and the TouchDesigner WebSe
|
|
|
82
113
|
*On Windows systems, include the drive letter like C: e.g. `C:\\path\\to\\your\\touchdesigner-mcp\\docker-compose.yml`*
|
|
83
114
|
</details>
|
|
84
115
|
|
|
85
|
-
<details>
|
|
86
|
-
<summary>Method 2: Using the NPM Package</summary>
|
|
87
|
-
|
|
88
|
-
To use the pre-built JS directly from Node.js:
|
|
89
|
-
|
|
90
|
-
[](https://www.youtube.com/watch?v=jFaUP1fYum0)
|
|
91
|
-
|
|
92
|
-
#### 1. Install the package
|
|
93
|
-
```bash
|
|
94
|
-
mkdir some && cd ./some # If you need a new directory
|
|
95
|
-
npm install touchdesigner-mcp-server
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
#### 2. Install the API Server in Your TouchDesigner Project:
|
|
99
|
-
|
|
100
|
-
Start TouchDesigner and import the `some/node_modules/touchdesigner-mcp-server/td/mcp_webserver_base.tox` component directly under the TouchDesigner project you want to control.
|
|
101
|
-
Example: Place it as `/project1/mcp_webserver_base`
|
|
102
|
-
|
|
103
|
-
Importing the tox will trigger the `some/node_modules/touchdesigner-mcp-server/td/import_modules.py` script, which loads modules such as API server controllers.
|
|
104
|
-
|
|
105
|
-

|
|
106
|
-
|
|
107
|
-
You can check boot logs by opening the Textport from the TouchDesigner menu.
|
|
108
|
-
|
|
109
|
-

|
|
110
|
-
|
|
111
|
-
#### 3. Configure your AI agent:
|
|
112
|
-
|
|
113
|
-
*Example for Claude Desktop*
|
|
114
|
-
```json
|
|
115
|
-
{
|
|
116
|
-
"mcpServers": {
|
|
117
|
-
"touchdesigner": {
|
|
118
|
-
"args": [
|
|
119
|
-
"/path/to/your/node_modules/touchdesigner-mcp-server/dist/index.js", // <-- Replace with the absolute path to node_modules/touchdesigner-mcp-server/dist/index.js
|
|
120
|
-
"--stdio"
|
|
121
|
-
],
|
|
122
|
-
"command": "node"
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
*On Windows systems, include the drive letter like C: e.g. `C:\\path\\to\\your\\node_modules\\touchdesigner-mcp-server\\dist\\index.js`*
|
|
129
|
-
</details>
|
|
130
116
|
|
|
131
|
-
|
|
117
|
+
## Verify Connection
|
|
132
118
|
|
|
133
119
|
If the MCP server is recognized, setup is complete.
|
|
134
120
|
If it's not recognized, try restarting your AI agent.
|
|
135
121
|
If you see an error at startup, try launching the agent again after starting TouchDesigner first.
|
|
136
122
|
When the API server is running properly in TouchDesigner, the agent can use the provided tools to operate TouchDesigner.
|
|
137
123
|
|
|
124
|
+
### Directory Structure Requirements
|
|
125
|
+
|
|
126
|
+
**Critical:** When using any method (Docker, npx), maintain the exact directory structure:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
td/
|
|
130
|
+
├── import_modules.py # Module loader script
|
|
131
|
+
├── mcp_webserver_base.tox # Main TouchDesigner component
|
|
132
|
+
└── modules/ # Python modules directory
|
|
133
|
+
├── mcp/ # MCP core logic
|
|
134
|
+
├── utils/ # Shared utilities
|
|
135
|
+
└── td_server/ # Generated API server code
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The `mcp_webserver_base.tox` component uses relative paths to locate Python modules. Moving or reorganizing these files will cause import errors in TouchDesigner.
|
|
139
|
+
|
|
138
140
|

|
|
139
141
|
|
|
140
142
|
|
|
@@ -176,21 +178,28 @@ Not implemented
|
|
|
176
178
|
|
|
177
179
|
## For Developers
|
|
178
180
|
|
|
179
|
-
###
|
|
181
|
+
### Quick Start for Development
|
|
180
182
|
|
|
181
|
-
1.
|
|
182
|
-
|
|
183
|
-
|
|
183
|
+
1. **Setup environment:**
|
|
184
|
+
```bash
|
|
185
|
+
cp dotenv .env
|
|
186
|
+
# Adjust TD_WEB_SERVER_HOST and TD_WEB_SERVER_PORT in .env file
|
|
187
|
+
```
|
|
184
188
|
|
|
185
|
-
|
|
189
|
+
2. **Build the project:**
|
|
190
|
+
```bash
|
|
191
|
+
make build # Docker-based build (recommended)
|
|
192
|
+
# OR
|
|
193
|
+
npm run build # Node.js-based build
|
|
194
|
+
```
|
|
186
195
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
3. **Available commands:**
|
|
197
|
+
```bash
|
|
198
|
+
npm run test # Run unit and integration tests
|
|
199
|
+
npm run dev # Launch MCP inspector for debugging
|
|
200
|
+
```
|
|
191
201
|
|
|
192
|
-
|
|
193
|
-
Launch @modelcontextprotocol/inspector to debug various features.
|
|
202
|
+
**Note:** When you update the code, restart both the MCP server and TouchDesigner to reflect changes.
|
|
194
203
|
|
|
195
204
|
### Project Structure Overview
|
|
196
205
|
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolve } from "node:path";
|
|
2
|
+
import path, { resolve } from "node:path";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { config } from "dotenv";
|
|
5
5
|
import { TouchDesignerServer } from "./server/touchDesignerServer.js";
|
|
@@ -28,7 +28,11 @@ export async function startServer() {
|
|
|
28
28
|
process.exit(1);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
if
|
|
31
|
+
// Start server if this file is executed directly
|
|
32
|
+
import { fileURLToPath } from "node:url";
|
|
33
|
+
const currentFilePath = path.normalize(fileURLToPath(import.meta.url));
|
|
34
|
+
const argvFilePath = path.normalize(process.argv[1]);
|
|
35
|
+
if (currentFilePath === argvFilePath) {
|
|
32
36
|
startServer().catch((error) => {
|
|
33
37
|
console.error("Failed to start server:", error);
|
|
34
38
|
process.exit(1);
|
|
@@ -85,17 +85,22 @@ export function registerTdTools(server, logger, tdClient) {
|
|
|
85
85
|
return handleToolError(error, logger, TOOL_NAMES.DELETE_TD_NODE, REFERENCE_COMMENT);
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
|
-
server.tool(TOOL_NAMES.GET_TD_NODES, "Get all nodes in the parent path", getNodesQueryParams.strict().shape, async (params) => {
|
|
88
|
+
server.tool(TOOL_NAMES.GET_TD_NODES, "Get all nodes in the parent path (lightweight by default for better performance)", getNodesQueryParams.strict().shape, async (params) => {
|
|
89
89
|
try {
|
|
90
90
|
const result = await tdClient.getNodes(params);
|
|
91
91
|
if (!result.success) {
|
|
92
92
|
throw result.error;
|
|
93
93
|
}
|
|
94
|
+
const nodeCount = result.data?.nodes?.length || 0;
|
|
95
|
+
const isLightweight = !params.includeProperties;
|
|
96
|
+
const performanceNote = isLightweight
|
|
97
|
+
? " (lightweight mode - set includeProperties=true for full node details)"
|
|
98
|
+
: " (full mode with properties)";
|
|
94
99
|
return {
|
|
95
100
|
content: [
|
|
96
101
|
{
|
|
97
102
|
type: "text",
|
|
98
|
-
text: `Project nodes retrieved: ${JSON.stringify(result, null, 2)}`,
|
|
103
|
+
text: `Project nodes retrieved (${nodeCount} nodes)${performanceNote}: ${JSON.stringify(result, null, 2)}`,
|
|
99
104
|
},
|
|
100
105
|
],
|
|
101
106
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Do not edit manually.
|
|
4
4
|
* TouchDesigner API
|
|
5
5
|
* OpenAPI schema for generating TouchDesigner API client code
|
|
6
|
-
* OpenAPI spec version: 0.
|
|
6
|
+
* OpenAPI spec version: 0.4.0-alpha.0
|
|
7
7
|
*/
|
|
8
8
|
import { customInstance } from '../../api/customInstance.js';
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Do not edit manually.
|
|
4
4
|
* TouchDesigner API
|
|
5
5
|
* OpenAPI schema for generating TouchDesigner API client code
|
|
6
|
-
* OpenAPI spec version: 0.
|
|
6
|
+
* OpenAPI spec version: 0.4.0-alpha.0
|
|
7
7
|
*/
|
|
8
8
|
import { z as zod } from 'zod';
|
|
9
9
|
/**
|
|
@@ -30,9 +30,11 @@ export const deleteNodeResponse = zod.object({
|
|
|
30
30
|
* @summary Get nodes in the path
|
|
31
31
|
*/
|
|
32
32
|
export const getNodesQueryPatternDefault = "*";
|
|
33
|
+
export const getNodesQueryIncludePropertiesDefault = false;
|
|
33
34
|
export const getNodesQueryParams = zod.object({
|
|
34
35
|
"parentPath": zod.string().describe('Parent path e.g., \"/project1\"'),
|
|
35
|
-
"pattern": zod.string().default(getNodesQueryPatternDefault).describe('Pattern to match against node names e.g., \"null*\"')
|
|
36
|
+
"pattern": zod.string().default(getNodesQueryPatternDefault).describe('Pattern to match against node names e.g., \"null*\"'),
|
|
37
|
+
"includeProperties": zod.boolean().optional().describe('Whether to include full node properties in the response (default false for better performance)')
|
|
36
38
|
});
|
|
37
39
|
export const getNodesResponse = zod.object({
|
|
38
40
|
"success": zod.boolean().describe('Whether the operation was successful'),
|
|
@@ -33,7 +33,7 @@ export class ConnectionManager {
|
|
|
33
33
|
catch (error) {
|
|
34
34
|
this.transport = null;
|
|
35
35
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
36
|
-
console.error("Fatal error starting server! Check TouchDesigner setup and starting webserver.", err);
|
|
36
|
+
console.error("Fatal error starting server! Check TouchDesigner setup and starting webserver. For detailed setup instructions, see https://github.com/8beeeaaat/touchdesigner-mcp", err);
|
|
37
37
|
return createErrorResult(err);
|
|
38
38
|
}
|
|
39
39
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "touchdesigner-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-alpha.0",
|
|
4
4
|
"description": "MCP server for TouchDesigner",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -41,9 +41,17 @@
|
|
|
41
41
|
"yaml": "^2.7.1"
|
|
42
42
|
},
|
|
43
43
|
"type": "module",
|
|
44
|
-
"main": "
|
|
44
|
+
"main": "dist/index.js",
|
|
45
|
+
"types": "dist/index.d.ts",
|
|
45
46
|
"bin": {
|
|
46
|
-
"touchdesigner-mcp-server": "dist/cli.js"
|
|
47
|
+
"touchdesigner-mcp-server": "dist/cli.js",
|
|
48
|
+
"touchdesigner-mcp": "dist/cli.js"
|
|
49
|
+
},
|
|
50
|
+
"exports": {
|
|
51
|
+
".": {
|
|
52
|
+
"import": "./dist/index.js",
|
|
53
|
+
"types": "./dist/index.d.ts"
|
|
54
|
+
}
|
|
47
55
|
},
|
|
48
56
|
"scripts": {
|
|
49
57
|
"build": "run-s build:*",
|
|
@@ -55,7 +55,7 @@ class ApiServiceProtocol(Protocol):
|
|
|
55
55
|
|
|
56
56
|
def get_td_info(self) -> Result: ...
|
|
57
57
|
|
|
58
|
-
def get_nodes(self, parent_path: str, pattern: Optional[str] = None) -> Result: ...
|
|
58
|
+
def get_nodes(self, parent_path: str, pattern: Optional[str] = None, include_properties: bool = False) -> Result: ...
|
|
59
59
|
|
|
60
60
|
def create_node(
|
|
61
61
|
self,
|
|
@@ -417,6 +417,7 @@ class APIControllerOpenAPI(IController):
|
|
|
417
417
|
self,
|
|
418
418
|
parentPath: str,
|
|
419
419
|
pattern: Optional[str] = None,
|
|
420
|
+
includeProperties: Optional[bool] = None,
|
|
420
421
|
body: Optional[str] = None,
|
|
421
422
|
**kwargs,
|
|
422
423
|
) -> Result:
|
|
@@ -426,11 +427,15 @@ class APIControllerOpenAPI(IController):
|
|
|
426
427
|
Args:
|
|
427
428
|
parentPath: Path of the parent node to get children from
|
|
428
429
|
pattern: Optional pattern to filter nodes by
|
|
430
|
+
includeProperties: Whether to include full node properties (default: False)
|
|
429
431
|
|
|
430
432
|
Returns:
|
|
431
433
|
List of nodes under the specified parent path
|
|
432
434
|
"""
|
|
433
|
-
|
|
435
|
+
# Convert camelCase to snake_case and provide default value
|
|
436
|
+
include_properties = includeProperties if includeProperties is not None else False
|
|
437
|
+
|
|
438
|
+
service_result = self._service.get_nodes(parentPath, pattern, include_properties)
|
|
434
439
|
response_data = GetNodes200Response().from_dict(service_result)
|
|
435
440
|
return response_data.to_dict()
|
|
436
441
|
|
|
@@ -132,12 +132,13 @@ class TouchDesignerApiService(IApiService):
|
|
|
132
132
|
node_info = self._get_node_summary(node)
|
|
133
133
|
return success_result(node_info)
|
|
134
134
|
|
|
135
|
-
def get_nodes(self, parent_path: str, pattern: Optional[str] = None) -> Result:
|
|
135
|
+
def get_nodes(self, parent_path: str, pattern: Optional[str] = None, include_properties: bool = False) -> Result:
|
|
136
136
|
"""Get nodes under the specified parent path, optionally filtered by pattern
|
|
137
137
|
|
|
138
138
|
Args:
|
|
139
139
|
parent_path: Path to the parent node
|
|
140
140
|
pattern: Pattern to filter nodes by name (e.g. "text*" for all nodes starting with "text")
|
|
141
|
+
include_properties: Whether to include full node properties (default False for better performance)
|
|
141
142
|
|
|
142
143
|
Returns:
|
|
143
144
|
Result: Success with list of nodes or error
|
|
@@ -157,7 +158,10 @@ class TouchDesignerApiService(IApiService):
|
|
|
157
158
|
log_message("Calling parent_node.findChildren(depth=1)", LogLevel.DEBUG)
|
|
158
159
|
nodes = parent_node.findChildren(depth=1)
|
|
159
160
|
|
|
160
|
-
|
|
161
|
+
if include_properties:
|
|
162
|
+
node_summaries = [self._get_node_summary(node) for node in nodes]
|
|
163
|
+
else:
|
|
164
|
+
node_summaries = [self._get_node_summary_light(node) for node in nodes]
|
|
161
165
|
|
|
162
166
|
return success_result({"nodes": node_summaries})
|
|
163
167
|
|
|
@@ -357,8 +361,6 @@ class TouchDesignerApiService(IApiService):
|
|
|
357
361
|
if node is None or not node.valid:
|
|
358
362
|
raise error_result(f"Node not found at path: {node_path}")
|
|
359
363
|
|
|
360
|
-
node_detail = self.get_node_detail(node_path)
|
|
361
|
-
current_properties = node_detail.get("data", {})
|
|
362
364
|
updated_properties = []
|
|
363
365
|
failed_properties = []
|
|
364
366
|
|
|
@@ -437,6 +439,24 @@ class TouchDesignerApiService(IApiService):
|
|
|
437
439
|
|
|
438
440
|
return params_dict
|
|
439
441
|
|
|
442
|
+
def _get_node_summary_light(self, node) -> Dict:
|
|
443
|
+
"""Get lightweight information about a node (without properties for better performance)"""
|
|
444
|
+
try:
|
|
445
|
+
node_info = {
|
|
446
|
+
"id": node.id,
|
|
447
|
+
"name": node.name,
|
|
448
|
+
"path": node.path,
|
|
449
|
+
"opType": node.OPType,
|
|
450
|
+
"properties": {}, # Empty properties for lightweight response
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return node_info
|
|
454
|
+
except Exception as e:
|
|
455
|
+
log_message(
|
|
456
|
+
f"Error collecting node information: {str(e)}", LogLevel.WARNING
|
|
457
|
+
)
|
|
458
|
+
return {"name": node.name if hasattr(node, "name") else "unknown"}
|
|
459
|
+
|
|
440
460
|
def _get_node_summary(self, node) -> Dict:
|
|
441
461
|
"""Get detailed information about a node"""
|
|
442
462
|
try:
|
|
@@ -94,7 +94,7 @@ def get_node_detail(node_path): # noqa: E501
|
|
|
94
94
|
return 'do some magic!'
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
def get_nodes(parent_path, pattern=None): # noqa: E501
|
|
97
|
+
def get_nodes(parent_path, pattern=None, include_properties=None): # noqa: E501
|
|
98
98
|
"""Get nodes in the path
|
|
99
99
|
|
|
100
100
|
# noqa: E501
|
|
@@ -103,6 +103,8 @@ def get_nodes(parent_path, pattern=None): # noqa: E501
|
|
|
103
103
|
:type parent_path: str
|
|
104
104
|
:param pattern: Pattern to match against node names e.g., \"null*\"
|
|
105
105
|
:type pattern: str
|
|
106
|
+
:param include_properties: Whether to include full node properties in the response (default false for better performance)
|
|
107
|
+
:type include_properties: bool
|
|
106
108
|
|
|
107
109
|
:rtype: Union[GetNodes200Response, Tuple[GetNodes200Response, int], Tuple[GetNodes200Response, int, Dict[str, str]]
|
|
108
110
|
"""
|
|
@@ -2,7 +2,7 @@ openapi: 3.0.0
|
|
|
2
2
|
info:
|
|
3
3
|
description: OpenAPI schema for generating TouchDesigner API client code
|
|
4
4
|
title: TouchDesigner API
|
|
5
|
-
version: 0.
|
|
5
|
+
version: 0.4.0-alpha.0
|
|
6
6
|
servers:
|
|
7
7
|
- url: "{baseUrl}"
|
|
8
8
|
variables:
|
|
@@ -47,6 +47,15 @@ paths:
|
|
|
47
47
|
default: '*'
|
|
48
48
|
description: "e.g., \"null*\""
|
|
49
49
|
type: string
|
|
50
|
+
- description: Whether to include full node properties in the response (default
|
|
51
|
+
false for better performance)
|
|
52
|
+
in: query
|
|
53
|
+
name: includeProperties
|
|
54
|
+
required: false
|
|
55
|
+
schema:
|
|
56
|
+
default: false
|
|
57
|
+
description: Include node properties in response
|
|
58
|
+
type: boolean
|
|
50
59
|
responses:
|
|
51
60
|
"200":
|
|
52
61
|
content:
|
|
@@ -119,7 +119,8 @@ class TestDefaultController(BaseTestCase):
|
|
|
119
119
|
Get nodes in the path
|
|
120
120
|
"""
|
|
121
121
|
query_string = [('parentPath', 'parent_path_example'),
|
|
122
|
-
('pattern', '*')
|
|
122
|
+
('pattern', '*'),
|
|
123
|
+
('includeProperties', False)]
|
|
123
124
|
headers = {
|
|
124
125
|
'Accept': 'application/json',
|
|
125
126
|
}
|