touchdesigner-mcp-server 0.2.13 → 0.3.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.
@@ -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.2.13
6
+ * OpenAPI spec version: 0.3.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.2.13
6
+ * OpenAPI spec version: 0.3.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'),
@@ -18,7 +18,7 @@ export class TouchDesignerServer {
18
18
  constructor() {
19
19
  this.server = new McpServer({
20
20
  name: "TouchDesigner",
21
- version: "0.2.13",
21
+ version: "0.3.0",
22
22
  }, {
23
23
  capabilities: {
24
24
  prompts: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "touchdesigner-mcp-server",
3
- "version": "0.2.13",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server for TouchDesigner",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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
- service_result = self._service.get_nodes(parentPath, pattern)
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
- node_summaries = [self._get_node_summary(node) for node in nodes]
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.2.13
5
+ version: 0.3.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
  }