touchdesigner-mcp-server 1.4.8 → 1.4.10

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 (50) hide show
  1. package/dist/api/customInstance.d.ts +5 -0
  2. package/dist/cli.d.ts +50 -0
  3. package/dist/core/compatibility.d.ts +102 -0
  4. package/dist/core/constants.d.ts +29 -0
  5. package/dist/core/errorHandling.d.ts +18 -0
  6. package/dist/core/logger.d.ts +24 -0
  7. package/dist/core/result.d.ts +25 -0
  8. package/dist/core/version.d.ts +21 -0
  9. package/dist/features/prompts/handlers/td_prompts.d.ts +6 -0
  10. package/dist/features/prompts/index.d.ts +1 -0
  11. package/dist/features/prompts/register.d.ts +6 -0
  12. package/dist/features/tools/handlers/tdTools.d.ts +4 -0
  13. package/dist/features/tools/handlers/tdTools.js +23 -256
  14. package/dist/features/tools/index.d.ts +3 -0
  15. package/dist/features/tools/metadata/touchDesignerToolMetadata.d.ts +29 -0
  16. package/dist/features/tools/metadata/touchDesignerToolMetadata.js +96 -474
  17. package/dist/features/tools/presenter/classListFormatter.d.ts +29 -0
  18. package/dist/features/tools/presenter/index.d.ts +18 -0
  19. package/dist/features/tools/presenter/markdownRenderer.d.ts +3 -0
  20. package/dist/features/tools/presenter/moduleHelpFormatter.d.ts +12 -0
  21. package/dist/features/tools/presenter/nodeDetailsFormatter.d.ts +16 -0
  22. package/dist/features/tools/presenter/nodeErrorsFormatter.d.ts +4 -0
  23. package/dist/features/tools/presenter/nodeListFormatter.d.ts +22 -0
  24. package/dist/features/tools/presenter/operationFormatter.d.ts +16 -0
  25. package/dist/features/tools/presenter/presenter.d.ts +10 -0
  26. package/dist/features/tools/presenter/responseFormatter.d.ts +83 -0
  27. package/dist/features/tools/presenter/scriptResultFormatter.d.ts +23 -0
  28. package/dist/features/tools/presenter/toolMetadataFormatter.d.ts +7 -0
  29. package/dist/features/tools/register.d.ts +7 -0
  30. package/dist/features/tools/toolDefinitions.d.ts +38 -0
  31. package/dist/features/tools/toolDefinitions.js +317 -0
  32. package/dist/features/tools/types.d.ts +43 -0
  33. package/dist/features/tools/utils/toolUtils.d.ts +0 -0
  34. package/dist/gen/endpoints/TouchDesignerAPI.d.ts +510 -0
  35. package/dist/gen/endpoints/TouchDesignerAPI.js +18 -18
  36. package/dist/gen/mcp/touchDesignerAPI.zod.d.ts +253 -0
  37. package/dist/gen/mcp/touchDesignerAPI.zod.js +27 -27
  38. package/dist/index.d.ts +3 -0
  39. package/dist/server/connectionManager.d.ts +25 -0
  40. package/dist/server/touchDesignerServer.d.ts +59 -0
  41. package/dist/tdClient/index.d.ts +7 -0
  42. package/dist/tdClient/touchDesignerClient.d.ts +167 -0
  43. package/dist/transport/config.d.ts +96 -0
  44. package/dist/transport/expressHttpManager.d.ts +86 -0
  45. package/dist/transport/factory.d.ts +81 -0
  46. package/dist/transport/index.d.ts +15 -0
  47. package/dist/transport/sessionManager.d.ts +180 -0
  48. package/dist/transport/transportRegistry.d.ts +92 -0
  49. package/dist/transport/validator.d.ts +43 -0
  50. package/package.json +6 -21
@@ -0,0 +1,5 @@
1
+ import { type AxiosError, type AxiosRequestConfig } from "axios";
2
+ export declare const AXIOS_INSTANCE: import("axios").AxiosInstance;
3
+ export declare const customInstance: <T>(config: AxiosRequestConfig, options?: AxiosRequestConfig) => Promise<T>;
4
+ export type ErrorType<E> = AxiosError<E>;
5
+ export type BodyType<BodyData> = BodyData;
package/dist/cli.d.ts ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import type { TransportConfig } from "./transport/config.js";
3
+ /**
4
+ * Parse command line arguments for TouchDesigner connection
5
+ */
6
+ export declare function parseArgs(args?: string[]): {
7
+ host: string;
8
+ port: number;
9
+ };
10
+ /**
11
+ * Parse transport configuration from command line arguments
12
+ *
13
+ * Detects if HTTP mode is requested via --mcp-http-port flag.
14
+ * If not specified, defaults to stdio mode.
15
+ *
16
+ * @param args - Command line arguments (defaults to process.argv.slice(2))
17
+ * @returns Transport configuration (stdio or streamable-http)
18
+ *
19
+ * @example
20
+ * ```bash
21
+ * # Stdio mode (default)
22
+ * touchdesigner-mcp-server --host=http://localhost --port=9981
23
+ *
24
+ * # HTTP mode
25
+ * touchdesigner-mcp-server --mcp-http-port=6280 --mcp-http-host=127.0.0.1
26
+ * ```
27
+ */
28
+ export declare function parseTransportConfig(args?: string[]): TransportConfig;
29
+ /**
30
+ * Start TouchDesigner MCP server
31
+ *
32
+ * Supports both stdio and HTTP transport modes based on command line arguments.
33
+ *
34
+ * @param params - Server startup parameters
35
+ * @param params.argv - Command line arguments
36
+ * @param params.nodeEnv - Node environment
37
+ *
38
+ * @example
39
+ * ```bash
40
+ * # Stdio mode (default)
41
+ * touchdesigner-mcp-server --host=http://localhost --port=9981
42
+ *
43
+ * # HTTP mode
44
+ * touchdesigner-mcp-server --mcp-http-port=6280 --host=http://localhost --port=9981
45
+ * ```
46
+ */
47
+ export declare function startServer(params?: {
48
+ nodeEnv?: string;
49
+ argv?: string[];
50
+ }): Promise<void>;
@@ -0,0 +1,102 @@
1
+ export declare const COMPATIBILITY_POLICY_TYPES: {
2
+ readonly BELOW_MIN_VERSION: "belowMinVersion";
3
+ readonly COMPATIBLE: "compatible";
4
+ readonly MAJOR_MISMATCH: "majorMismatch";
5
+ readonly NEWER_MINOR: "newerMinor";
6
+ readonly NO_VERSION: "noVersion";
7
+ readonly OLDER_MINOR: "olderMinor";
8
+ readonly PATCH_DIFF: "patchDiff";
9
+ };
10
+ export declare const COMPATIBILITY_POLICY_ERROR_LEVELS: {
11
+ readonly ALLOW: "info";
12
+ readonly ERROR: "error";
13
+ readonly WARNING: "warning";
14
+ };
15
+ export type CompatibilityPolicyType = (typeof COMPATIBILITY_POLICY_TYPES)[keyof typeof COMPATIBILITY_POLICY_TYPES];
16
+ export type CompatibilityPolicyErrorLevel = (typeof COMPATIBILITY_POLICY_ERROR_LEVELS)[keyof typeof COMPATIBILITY_POLICY_ERROR_LEVELS];
17
+ export declare const getCompatibilityPolicyType: (params: {
18
+ mcpVersion: string;
19
+ apiVersion: string;
20
+ }) => CompatibilityPolicyType;
21
+ export declare const getCompatibilityPolicy: (type: CompatibilityPolicyType) => {
22
+ readonly compatible: false;
23
+ readonly level: "error";
24
+ readonly message: typeof generateNoVersionMessage;
25
+ } | {
26
+ readonly compatible: false;
27
+ readonly level: "error";
28
+ readonly message: typeof generateMinVersionMessage;
29
+ } | {
30
+ readonly compatible: false;
31
+ readonly level: "error";
32
+ readonly message: typeof generateMajorMismatchMessage;
33
+ } | {
34
+ readonly compatible: true;
35
+ readonly level: "warning";
36
+ readonly message: typeof generateNewerMinorMessage;
37
+ } | {
38
+ readonly compatible: true;
39
+ readonly level: "warning";
40
+ readonly message: typeof generateOlderMinorMessage;
41
+ } | {
42
+ readonly compatible: true;
43
+ readonly level: "info";
44
+ readonly message: typeof generatePatchDiffMessage;
45
+ } | {
46
+ readonly compatible: true;
47
+ readonly level: "info";
48
+ readonly message: typeof generateFullyCompatibleMessage;
49
+ };
50
+ /**
51
+ * Generate error message for unknown version information
52
+ */
53
+ export declare function generateNoVersionMessage(args: {
54
+ apiVersion: string;
55
+ mcpVersion: string;
56
+ }): string;
57
+ /**
58
+ * Generate error message for MAJOR version mismatch
59
+ */
60
+ export declare function generateMajorMismatchMessage(args: {
61
+ apiVersion: string;
62
+ mcpVersion: string;
63
+ }): string;
64
+ /**
65
+ * Generate error message when API version is below minimum compatible version
66
+ */
67
+ export declare function generateMinVersionMessage(args: {
68
+ apiVersion: string;
69
+ minRequired: string;
70
+ }): string;
71
+ /**
72
+ * Generate warning message when MCP server has newer MINOR version
73
+ */
74
+ export declare function generateNewerMinorMessage(args: {
75
+ apiVersion: string;
76
+ mcpVersion: string;
77
+ }): string;
78
+ /**
79
+ * Generate warning message when API server has newer MINOR version
80
+ */
81
+ export declare function generateOlderMinorMessage(args: {
82
+ apiVersion: string;
83
+ mcpVersion: string;
84
+ }): string;
85
+ /**
86
+ * Generate warning message when PATCH versions differ
87
+ */
88
+ export declare function generatePatchDiffMessage(args: {
89
+ apiVersion: string;
90
+ mcpVersion: string;
91
+ }): string;
92
+ /**
93
+ * Generate info message when versions are fully compatible
94
+ *
95
+ * @param mcpVersion MCP server version
96
+ * @param apiVersion TouchDesigner API server version
97
+ * @returns Info message
98
+ */
99
+ export declare function generateFullyCompatibleMessage(args: {
100
+ apiVersion: string;
101
+ mcpVersion: string;
102
+ }): string;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Reference URLs for TouchDesigner Python documentation
3
+ */
4
+ export declare const TD_PYTHON_CLASS_REFERENCE_BASE_URL = "https://docs.derivative.ca";
5
+ export declare const TD_PYTHON_CLASS_REFERENCE_INDEX_URL = "https://docs.derivative.ca/Python_Classes_and_Modules";
6
+ /**
7
+ * Reference Tool Names for TouchDesigner MCP
8
+ */
9
+ export declare const TOOL_NAMES: {
10
+ readonly CREATE_TD_NODE: "create_td_node";
11
+ readonly DELETE_TD_NODE: "delete_td_node";
12
+ readonly DESCRIBE_TD_TOOLS: "describe_td_tools";
13
+ readonly EXECUTE_NODE_METHOD: "exec_node_method";
14
+ readonly EXECUTE_PYTHON_SCRIPT: "execute_python_script";
15
+ readonly GET_TD_CLASS_DETAILS: "get_td_class_details";
16
+ readonly GET_TD_CLASSES: "get_td_classes";
17
+ readonly GET_TD_INFO: "get_td_info";
18
+ readonly GET_TD_MODULE_HELP: "get_td_module_help";
19
+ readonly GET_TD_NODE_ERRORS: "get_td_node_errors";
20
+ readonly GET_TD_NODE_PARAMETERS: "get_td_node_parameters";
21
+ readonly GET_TD_NODES: "get_td_nodes";
22
+ readonly UPDATE_TD_NODE_PARAMETERS: "update_td_node_parameters";
23
+ };
24
+ export declare const REFERENCE_COMMENT = "Check reference resources: https://docs.derivative.ca/Python_Classes_and_Modules";
25
+ export declare const PROMPT_NAMES: {
26
+ readonly CHECK_NODE_ERRORS: "Check node errors";
27
+ readonly NODE_CONNECTION: "Node connection";
28
+ readonly SEARCH_NODE: "Search node";
29
+ };
@@ -0,0 +1,18 @@
1
+ import type { ToolNames } from "../features/tools/index.js";
2
+ import type { ILogger } from "./logger.js";
3
+ /**
4
+ * Standard API error response structure compatible with MCP SDK
5
+ */
6
+ interface ErrorResponse {
7
+ [key: string]: unknown;
8
+ isError: true;
9
+ content: Array<{
10
+ type: "text";
11
+ text: string;
12
+ }>;
13
+ }
14
+ /**
15
+ * Handles API errors consistently across the application
16
+ */
17
+ export declare function handleToolError(error: unknown, logger: ILogger, toolName: ToolNames, referenceComment?: string): ErrorResponse;
18
+ export {};
@@ -0,0 +1,24 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { LoggingMessageNotification } from "@modelcontextprotocol/sdk/types.js";
3
+ /**
4
+ * Logger interface definition
5
+ */
6
+ export interface ILogger {
7
+ sendLog(args: LoggingMessageNotification["params"]): void;
8
+ }
9
+ /**
10
+ * MCP compatible logger implementation
11
+ * Handles "Not connected" errors gracefully
12
+ */
13
+ export declare class McpLogger implements ILogger {
14
+ private server;
15
+ constructor(server: McpServer);
16
+ sendLog(args: LoggingMessageNotification["params"]): void;
17
+ }
18
+ /**
19
+ * Console Logger implementation for standalone use (e.g., HTTP mode setup)
20
+ * Outputs to stderr to avoid interfering with stdio transport
21
+ */
22
+ export declare class ConsoleLogger implements ILogger {
23
+ sendLog(args: LoggingMessageNotification["params"]): void;
24
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Result type pattern for handling operation results
3
+ * Success case contains data, failure case contains error
4
+ */
5
+ export type Result<T, E = Error> = {
6
+ success: true;
7
+ data: T;
8
+ } | {
9
+ success: false;
10
+ error: E;
11
+ };
12
+ /**
13
+ * Creates a success result with the provided data
14
+ */
15
+ export declare function createSuccessResult<T>(data: T): {
16
+ success: true;
17
+ data: T;
18
+ };
19
+ /**
20
+ * Creates an error result with the provided error
21
+ */
22
+ export declare function createErrorResult<E = Error>(error: E): {
23
+ success: false;
24
+ error: E;
25
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Current MCP server version
3
+ */
4
+ export declare const getMcpServerVersion: () => string;
5
+ export declare const MCP_SERVER_VERSION: string;
6
+ /**
7
+ * Minimum compatible TouchDesigner API Server version required by the MCP server
8
+ *
9
+ * Loaded from package.json's mcpCompatibility.minApiVersion field.
10
+ * Falls back to the current package version if undefined.
11
+ *
12
+ * API Server must be at or above this version.
13
+ * - MAJOR mismatch: Error
14
+ * - MINOR/PATCH differences: Warning or allow
15
+ *
16
+ * Update when:
17
+ * - Introducing breaking API changes
18
+ * - Making incompatible changes to OpenAPI schema
19
+ */
20
+ export declare const getMinCompatibleApiVersion: () => string;
21
+ export declare const MIN_COMPATIBLE_API_VERSION: string;
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ILogger } from "../../../core/logger.js";
3
+ /**
4
+ * Register prompt handlers with MCP server
5
+ */
6
+ export declare function registerTdPrompts(server: McpServer, logger: ILogger): void;
@@ -0,0 +1 @@
1
+ export * from "./register.js";
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ILogger } from "../../core/logger.js";
3
+ /**
4
+ * Register prompt handlers with MCP server
5
+ */
6
+ export declare function registerPrompts(server: McpServer, logger: ILogger): void;
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ILogger } from "../../../core/logger.js";
3
+ import type { TouchDesignerClient } from "../../../tdClient/touchDesignerClient.js";
4
+ export declare function registerTdTools(server: McpServer, logger: ILogger, tdClient: TouchDesignerClient): void;
@@ -1,22 +1,10 @@
1
1
  import { z } from "zod";
2
- import { REFERENCE_COMMENT, TOOL_NAMES } from "../../../core/constants.js";
2
+ import { TOOL_NAMES } from "../../../core/constants.js";
3
3
  import { handleToolError } from "../../../core/errorHandling.js";
4
- import { CreateNodeBody, DeleteNodeQueryParams, ExecNodeMethodBody, ExecPythonScriptBody, GetModuleHelpQueryParams, GetNodeDetailQueryParams, GetNodeErrorsQueryParams, GetNodesQueryParams, GetTdPythonClassDetailsParams, UpdateNodeBody, } from "../../../gen/mcp/touchDesignerAPI.zod.js";
5
- import { getTouchDesignerToolMetadata } from "../metadata/touchDesignerToolMetadata.js";
6
- import { formatClassDetails, formatClassList, formatCreateNodeResult, formatDeleteNodeResult, formatExecNodeMethodResult, formatModuleHelp, formatNodeDetails, formatNodeErrors, formatNodeList, formatScriptResult, formatTdInfo, formatToolMetadata, formatUpdateNodeResult, } from "../presenter/index.js";
7
- import { detailOnlyFormattingSchema, formattingOptionsSchema, } from "../types.js";
8
- const execPythonScriptToolSchema = ExecPythonScriptBody.extend(detailOnlyFormattingSchema.shape);
9
- const tdInfoToolSchema = detailOnlyFormattingSchema;
10
- const getNodesToolSchema = GetNodesQueryParams.extend(formattingOptionsSchema.shape);
11
- const getNodeDetailToolSchema = GetNodeDetailQueryParams.extend(formattingOptionsSchema.shape);
12
- const getNodeErrorsToolSchema = GetNodeErrorsQueryParams.extend(formattingOptionsSchema.shape);
13
- const createNodeToolSchema = CreateNodeBody.extend(detailOnlyFormattingSchema.shape);
14
- const updateNodeToolSchema = UpdateNodeBody.extend(detailOnlyFormattingSchema.shape);
15
- const deleteNodeToolSchema = DeleteNodeQueryParams.extend(detailOnlyFormattingSchema.shape);
16
- const classListToolSchema = formattingOptionsSchema;
17
- const classDetailToolSchema = GetTdPythonClassDetailsParams.extend(formattingOptionsSchema.shape);
18
- const moduleHelpToolSchema = GetModuleHelpQueryParams.extend(detailOnlyFormattingSchema.shape);
19
- const execNodeMethodToolSchema = ExecNodeMethodBody.extend(detailOnlyFormattingSchema.shape);
4
+ import { buildToolMetadata, } from "../metadata/touchDesignerToolMetadata.js";
5
+ import { formatToolMetadata } from "../presenter/index.js";
6
+ import { TOOL_DEFINITIONS } from "../toolDefinitions.js";
7
+ import { detailOnlyFormattingSchema } from "../types.js";
20
8
  const describeToolsSchema = detailOnlyFormattingSchema.extend({
21
9
  filter: z
22
10
  .string()
@@ -25,7 +13,21 @@ const describeToolsSchema = detailOnlyFormattingSchema.extend({
25
13
  .optional(),
26
14
  });
27
15
  export function registerTdTools(server, logger, tdClient) {
28
- const toolMetadataEntries = getTouchDesignerToolMetadata();
16
+ // Register every TouchDesigner operation from the single source of truth.
17
+ for (const definition of TOOL_DEFINITIONS) {
18
+ server.tool(definition.name, definition.description, definition.schema.strict().shape, async (params = {}) => {
19
+ try {
20
+ const text = await definition.run({ logger, params, tdClient });
21
+ return createToolResult(tdClient, text);
22
+ }
23
+ catch (error) {
24
+ return handleToolError(error, logger, definition.name, definition.errorComment);
25
+ }
26
+ });
27
+ }
28
+ // `describe_td_tools` is the meta tool: it documents the tools above rather
29
+ // than calling TouchDesigner, so it is registered on its own.
30
+ const toolMetadataEntries = buildToolMetadata(TOOL_DEFINITIONS);
29
31
  server.tool(TOOL_NAMES.DESCRIBE_TD_TOOLS, "Generate a filesystem-oriented manifest of available TouchDesigner tools", describeToolsSchema.strict().shape, async (params = {}) => {
30
32
  try {
31
33
  const { detailLevel, responseFormat, filter } = params;
@@ -38,12 +40,7 @@ export function registerTdTools(server, logger, tdClient) {
38
40
  ? `No TouchDesigner tools matched filter "${filter}".`
39
41
  : "No TouchDesigner tools are registered.";
40
42
  return {
41
- content: [
42
- {
43
- text: message,
44
- type: "text",
45
- },
46
- ],
43
+ content: [{ text: message, type: "text" }],
47
44
  };
48
45
  }
49
46
  const formattedText = formatToolMetadata(filteredEntries, {
@@ -52,247 +49,17 @@ export function registerTdTools(server, logger, tdClient) {
52
49
  responseFormat,
53
50
  });
54
51
  return {
55
- content: [
56
- {
57
- text: formattedText,
58
- type: "text",
59
- },
60
- ],
52
+ content: [{ text: formattedText, type: "text" }],
61
53
  };
62
54
  }
63
55
  catch (error) {
64
56
  return handleToolError(error, logger, TOOL_NAMES.DESCRIBE_TD_TOOLS);
65
57
  }
66
58
  });
67
- server.tool(TOOL_NAMES.GET_TD_INFO, "Get server information from TouchDesigner", tdInfoToolSchema.strict().shape, async (params = {}) => {
68
- try {
69
- const { detailLevel, responseFormat } = params;
70
- const result = await tdClient.getTdInfo();
71
- if (!result.success) {
72
- throw result.error;
73
- }
74
- const formattedText = formatTdInfo(result.data, {
75
- detailLevel: detailLevel ?? "summary",
76
- responseFormat,
77
- });
78
- return createToolResult(tdClient, formattedText);
79
- }
80
- catch (error) {
81
- return handleToolError(error, logger, TOOL_NAMES.GET_TD_INFO);
82
- }
83
- });
84
- server.tool(TOOL_NAMES.EXECUTE_PYTHON_SCRIPT, "Execute a Python script in TouchDesigner (detailLevel=minimal|summary|detailed, responseFormat=json|yaml|markdown)", execPythonScriptToolSchema.strict().shape, async (params) => {
85
- try {
86
- const { detailLevel, responseFormat, ...scriptParams } = params;
87
- logger.sendLog({
88
- data: `Executing script: ${scriptParams.script}`,
89
- level: "debug",
90
- });
91
- const result = await tdClient.execPythonScript(scriptParams);
92
- if (!result.success) {
93
- throw result.error;
94
- }
95
- // Use formatter for token-optimized response
96
- const formattedText = formatScriptResult(result, scriptParams.script, {
97
- detailLevel: detailLevel ?? "summary",
98
- responseFormat,
99
- });
100
- return createToolResult(tdClient, formattedText);
101
- }
102
- catch (error) {
103
- return handleToolError(error, logger, TOOL_NAMES.EXECUTE_PYTHON_SCRIPT);
104
- }
105
- });
106
- server.tool(TOOL_NAMES.CREATE_TD_NODE, "Create a new node in TouchDesigner", createNodeToolSchema.strict().shape, async (params) => {
107
- try {
108
- const { detailLevel, responseFormat, ...createParams } = params;
109
- const result = await tdClient.createNode(createParams);
110
- if (!result.success) {
111
- throw result.error;
112
- }
113
- const formattedText = formatCreateNodeResult(result.data, {
114
- detailLevel: detailLevel ?? "summary",
115
- responseFormat,
116
- });
117
- return createToolResult(tdClient, formattedText);
118
- }
119
- catch (error) {
120
- return handleToolError(error, logger, TOOL_NAMES.CREATE_TD_NODE, REFERENCE_COMMENT);
121
- }
122
- });
123
- server.tool(TOOL_NAMES.DELETE_TD_NODE, "Delete an existing node in TouchDesigner", deleteNodeToolSchema.strict().shape, async (params) => {
124
- try {
125
- const { detailLevel, responseFormat, ...deleteParams } = params;
126
- const result = await tdClient.deleteNode(deleteParams);
127
- if (!result.success) {
128
- throw result.error;
129
- }
130
- const formattedText = formatDeleteNodeResult(result.data, {
131
- detailLevel: detailLevel ?? "summary",
132
- responseFormat,
133
- });
134
- return createToolResult(tdClient, formattedText);
135
- }
136
- catch (error) {
137
- return handleToolError(error, logger, TOOL_NAMES.DELETE_TD_NODE, REFERENCE_COMMENT);
138
- }
139
- });
140
- server.tool(TOOL_NAMES.GET_TD_NODES, "List nodes under a path with token-optimized output (detailLevel+limit supported)", getNodesToolSchema.strict().shape, async (params) => {
141
- try {
142
- const { detailLevel, limit, responseFormat, ...queryParams } = params;
143
- const result = await tdClient.getNodes(queryParams);
144
- if (!result.success) {
145
- throw result.error;
146
- }
147
- // Use formatter for token-optimized response
148
- const fallbackMode = queryParams.includeProperties
149
- ? "detailed"
150
- : "summary";
151
- const formattedText = formatNodeList(result.data, {
152
- detailLevel: detailLevel ?? fallbackMode,
153
- limit,
154
- responseFormat,
155
- });
156
- return createToolResult(tdClient, formattedText);
157
- }
158
- catch (error) {
159
- return handleToolError(error, logger, TOOL_NAMES.GET_TD_NODES, REFERENCE_COMMENT);
160
- }
161
- });
162
- server.tool(TOOL_NAMES.GET_TD_NODE_PARAMETERS, "Get node parameters with concise/detailed formatting (detailLevel+limit supported)", getNodeDetailToolSchema.strict().shape, async (params) => {
163
- try {
164
- const { detailLevel, limit, responseFormat, ...queryParams } = params;
165
- const result = await tdClient.getNodeDetail(queryParams);
166
- if (!result.success) {
167
- throw result.error;
168
- }
169
- // Use formatter for token-optimized response
170
- const formattedText = formatNodeDetails(result.data, {
171
- detailLevel: detailLevel ?? "summary",
172
- limit,
173
- responseFormat,
174
- });
175
- return createToolResult(tdClient, formattedText);
176
- }
177
- catch (error) {
178
- return handleToolError(error, logger, TOOL_NAMES.GET_TD_NODE_PARAMETERS, REFERENCE_COMMENT);
179
- }
180
- });
181
- server.tool(TOOL_NAMES.GET_TD_NODE_ERRORS, "Check node and descendant errors reported by TouchDesigner", getNodeErrorsToolSchema.strict().shape, async (params) => {
182
- try {
183
- const { detailLevel, limit, responseFormat, ...queryParams } = params;
184
- const result = await tdClient.getNodeErrors(queryParams);
185
- if (!result.success) {
186
- throw result.error;
187
- }
188
- const formattedText = formatNodeErrors(result.data, {
189
- detailLevel: detailLevel ?? "summary",
190
- limit,
191
- responseFormat,
192
- });
193
- return createToolResult(tdClient, formattedText);
194
- }
195
- catch (error) {
196
- return handleToolError(error, logger, TOOL_NAMES.GET_TD_NODE_ERRORS, REFERENCE_COMMENT);
197
- }
198
- });
199
- server.tool(TOOL_NAMES.UPDATE_TD_NODE_PARAMETERS, "Update parameters of a specific node in TouchDesigner", updateNodeToolSchema.strict().shape, async (params) => {
200
- try {
201
- const { detailLevel, responseFormat, ...updateParams } = params;
202
- const result = await tdClient.updateNode(updateParams);
203
- if (!result.success) {
204
- throw result.error;
205
- }
206
- const formattedText = formatUpdateNodeResult(result.data, {
207
- detailLevel: detailLevel ?? "summary",
208
- responseFormat,
209
- });
210
- return createToolResult(tdClient, formattedText);
211
- }
212
- catch (error) {
213
- return handleToolError(error, logger, TOOL_NAMES.UPDATE_TD_NODE_PARAMETERS, REFERENCE_COMMENT);
214
- }
215
- });
216
- server.tool(TOOL_NAMES.EXECUTE_NODE_METHOD, "Execute a method on a specific node in TouchDesigner", execNodeMethodToolSchema.strict().shape, async (params) => {
217
- try {
218
- const { detailLevel, responseFormat, ...execParams } = params;
219
- const { nodePath, method, args, kwargs } = execParams;
220
- const result = await tdClient.execNodeMethod(execParams);
221
- if (!result.success) {
222
- throw result.error;
223
- }
224
- const formattedText = formatExecNodeMethodResult(result.data, { args, kwargs, method, nodePath }, { detailLevel: detailLevel ?? "summary", responseFormat });
225
- return createToolResult(tdClient, formattedText);
226
- }
227
- catch (error) {
228
- logger.sendLog({
229
- data: error,
230
- level: "error",
231
- });
232
- return handleToolError(error, logger, TOOL_NAMES.EXECUTE_NODE_METHOD, REFERENCE_COMMENT);
233
- }
234
- });
235
- server.tool(TOOL_NAMES.GET_TD_CLASSES, "List TouchDesigner Python classes/modules (detailLevel+limit supported)", classListToolSchema.strict().shape, async (params = {}) => {
236
- try {
237
- const result = await tdClient.getClasses();
238
- if (!result.success) {
239
- throw result.error;
240
- }
241
- // Use formatter for token-optimized response
242
- const formattedText = formatClassList(result.data, {
243
- detailLevel: params.detailLevel ?? "summary",
244
- limit: params.limit ?? 50,
245
- responseFormat: params.responseFormat,
246
- });
247
- return createToolResult(tdClient, formattedText);
248
- }
249
- catch (error) {
250
- return handleToolError(error, logger, TOOL_NAMES.GET_TD_CLASSES, REFERENCE_COMMENT);
251
- }
252
- });
253
- server.tool(TOOL_NAMES.GET_TD_CLASS_DETAILS, "Get information about a TouchDesigner class/module (detailLevel+limit supported)", classDetailToolSchema.strict().shape, async (params) => {
254
- try {
255
- const { className, detailLevel, limit, responseFormat } = params;
256
- const result = await tdClient.getClassDetails(className);
257
- if (!result.success) {
258
- throw result.error;
259
- }
260
- // Use formatter for token-optimized response
261
- const formattedText = formatClassDetails(result.data, {
262
- detailLevel: detailLevel ?? "summary",
263
- limit: limit ?? 30,
264
- responseFormat,
265
- });
266
- return createToolResult(tdClient, formattedText);
267
- }
268
- catch (error) {
269
- return handleToolError(error, logger, TOOL_NAMES.GET_TD_CLASS_DETAILS, REFERENCE_COMMENT);
270
- }
271
- });
272
- server.tool(TOOL_NAMES.GET_TD_MODULE_HELP, "Retrieve Python help() text for a TouchDesigner module or class", moduleHelpToolSchema.strict().shape, async (params) => {
273
- try {
274
- const { detailLevel, moduleName, responseFormat } = params;
275
- const result = await tdClient.getModuleHelp({ moduleName });
276
- if (!result.success) {
277
- throw result.error;
278
- }
279
- const formattedText = formatModuleHelp(result.data, {
280
- detailLevel: detailLevel ?? "summary",
281
- responseFormat,
282
- });
283
- return createToolResult(tdClient, formattedText);
284
- }
285
- catch (error) {
286
- return handleToolError(error, logger, TOOL_NAMES.GET_TD_MODULE_HELP);
287
- }
288
- });
289
59
  }
290
60
  const createToolResult = (tdClient, text) => {
291
61
  const content = [
292
- {
293
- text,
294
- type: "text",
295
- },
62
+ { text, type: "text" },
296
63
  ];
297
64
  const additionalContents = tdClient.getAdditionalToolResultContents();
298
65
  if (additionalContents) {
@@ -0,0 +1,3 @@
1
+ import type { TOOL_NAMES } from "../../core/constants.js";
2
+ export * from "./register.js";
3
+ export type ToolNames = (typeof TOOL_NAMES)[keyof typeof TOOL_NAMES];
@@ -0,0 +1,29 @@
1
+ import type { z } from "zod";
2
+ import type { ToolNames } from "../index.js";
3
+ import { type ToolCategory, type ToolDefinition } from "../toolDefinitions.js";
4
+ export type { ToolCategory };
5
+ export interface ToolParameterMetadata {
6
+ name: string;
7
+ type: string;
8
+ required: boolean;
9
+ description?: string;
10
+ }
11
+ export interface ToolMetadata {
12
+ tool: ToolNames;
13
+ modulePath: string;
14
+ functionName: string;
15
+ description: string;
16
+ category: ToolCategory;
17
+ parameters: ToolParameterMetadata[];
18
+ returns: string;
19
+ example: string;
20
+ notes?: string;
21
+ }
22
+ /**
23
+ * Builds the `describe_td_tools` manifest from the tool table. Parameter
24
+ * metadata is introspected from each tool's Zod schema, so it always reflects
25
+ * the schema that is actually registered (sourced from the OpenAPI spec).
26
+ */
27
+ export declare function buildToolMetadata(definitions?: readonly ToolDefinition[]): ToolMetadata[];
28
+ /** Introspects a Zod object schema into flat parameter metadata. */
29
+ export declare function deriveParameters(schema: z.ZodObject<z.ZodRawShape>): ToolParameterMetadata[];