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.
- package/dist/api/customInstance.d.ts +5 -0
- package/dist/cli.d.ts +50 -0
- package/dist/core/compatibility.d.ts +102 -0
- package/dist/core/constants.d.ts +29 -0
- package/dist/core/errorHandling.d.ts +18 -0
- package/dist/core/logger.d.ts +24 -0
- package/dist/core/result.d.ts +25 -0
- package/dist/core/version.d.ts +21 -0
- package/dist/features/prompts/handlers/td_prompts.d.ts +6 -0
- package/dist/features/prompts/index.d.ts +1 -0
- package/dist/features/prompts/register.d.ts +6 -0
- package/dist/features/tools/handlers/tdTools.d.ts +4 -0
- package/dist/features/tools/handlers/tdTools.js +23 -256
- package/dist/features/tools/index.d.ts +3 -0
- package/dist/features/tools/metadata/touchDesignerToolMetadata.d.ts +29 -0
- package/dist/features/tools/metadata/touchDesignerToolMetadata.js +96 -474
- package/dist/features/tools/presenter/classListFormatter.d.ts +29 -0
- package/dist/features/tools/presenter/index.d.ts +18 -0
- package/dist/features/tools/presenter/markdownRenderer.d.ts +3 -0
- package/dist/features/tools/presenter/moduleHelpFormatter.d.ts +12 -0
- package/dist/features/tools/presenter/nodeDetailsFormatter.d.ts +16 -0
- package/dist/features/tools/presenter/nodeErrorsFormatter.d.ts +4 -0
- package/dist/features/tools/presenter/nodeListFormatter.d.ts +22 -0
- package/dist/features/tools/presenter/operationFormatter.d.ts +16 -0
- package/dist/features/tools/presenter/presenter.d.ts +10 -0
- package/dist/features/tools/presenter/responseFormatter.d.ts +83 -0
- package/dist/features/tools/presenter/scriptResultFormatter.d.ts +23 -0
- package/dist/features/tools/presenter/toolMetadataFormatter.d.ts +7 -0
- package/dist/features/tools/register.d.ts +7 -0
- package/dist/features/tools/toolDefinitions.d.ts +38 -0
- package/dist/features/tools/toolDefinitions.js +317 -0
- package/dist/features/tools/types.d.ts +43 -0
- package/dist/features/tools/utils/toolUtils.d.ts +0 -0
- package/dist/gen/endpoints/TouchDesignerAPI.d.ts +510 -0
- package/dist/gen/endpoints/TouchDesignerAPI.js +18 -18
- package/dist/gen/mcp/touchDesignerAPI.zod.d.ts +253 -0
- package/dist/gen/mcp/touchDesignerAPI.zod.js +27 -27
- package/dist/index.d.ts +3 -0
- package/dist/server/connectionManager.d.ts +25 -0
- package/dist/server/touchDesignerServer.d.ts +59 -0
- package/dist/tdClient/index.d.ts +7 -0
- package/dist/tdClient/touchDesignerClient.d.ts +167 -0
- package/dist/transport/config.d.ts +96 -0
- package/dist/transport/expressHttpManager.d.ts +86 -0
- package/dist/transport/factory.d.ts +81 -0
- package/dist/transport/index.d.ts +15 -0
- package/dist/transport/sessionManager.d.ts +180 -0
- package/dist/transport/transportRegistry.d.ts +92 -0
- package/dist/transport/validator.d.ts +43 -0
- package/package.json +6 -21
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node List Formatter
|
|
3
|
+
*
|
|
4
|
+
* Formats TouchDesigner node lists with token-optimized output.
|
|
5
|
+
* Used by GET_TD_NODES tool.
|
|
6
|
+
*/
|
|
7
|
+
import type { TdNode } from "../../../gen/endpoints/TouchDesignerAPI.js";
|
|
8
|
+
import type { FormatterOptions } from "./responseFormatter.js";
|
|
9
|
+
/**
|
|
10
|
+
* Node list data structure (matches API response)
|
|
11
|
+
*/
|
|
12
|
+
export interface NodeListData {
|
|
13
|
+
nodes?: TdNode[];
|
|
14
|
+
parentPath?: string;
|
|
15
|
+
pattern?: string;
|
|
16
|
+
includeProperties?: boolean;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Format node list based on detail level
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatNodeList(data: NodeListData | undefined, options?: FormatterOptions): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CreateNode200Data, DeleteNode200Data, ExecNodeMethod200Data, GetTdInfo200Data, UpdateNode200Data } from "../../../gen/endpoints/TouchDesignerAPI.js";
|
|
2
|
+
import type { FormatterOptions } from "./responseFormatter.js";
|
|
3
|
+
type FormatterOpts = Pick<FormatterOptions, "detailLevel" | "responseFormat">;
|
|
4
|
+
export declare function formatTdInfo(data: GetTdInfo200Data, options?: FormatterOpts): string;
|
|
5
|
+
export declare function formatCreateNodeResult(data: CreateNode200Data, options?: FormatterOpts): string;
|
|
6
|
+
export declare function formatUpdateNodeResult(data: UpdateNode200Data, options?: FormatterOpts): string;
|
|
7
|
+
export declare function formatDeleteNodeResult(data: DeleteNode200Data, options?: FormatterOpts): string;
|
|
8
|
+
export declare function formatExecNodeMethodResult(data: ExecNodeMethod200Data | {
|
|
9
|
+
result?: unknown;
|
|
10
|
+
} | null | undefined, context: {
|
|
11
|
+
nodePath: string;
|
|
12
|
+
method: string;
|
|
13
|
+
args?: unknown[];
|
|
14
|
+
kwargs?: Record<string, unknown>;
|
|
15
|
+
}, options?: FormatterOpts): string;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type PresenterFormat = "json" | "yaml" | "markdown";
|
|
2
|
+
export declare const DEFAULT_PRESENTER_FORMAT: PresenterFormat;
|
|
3
|
+
export interface PresenterPayload {
|
|
4
|
+
text: string;
|
|
5
|
+
detailLevel?: string;
|
|
6
|
+
structured?: unknown;
|
|
7
|
+
context?: Record<string, unknown>;
|
|
8
|
+
template?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function presentStructuredData(payload: PresenterPayload, format?: PresenterFormat): string;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response Formatter Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides token-optimized formatting for MCP tool responses.
|
|
5
|
+
* Based on the design document: docs/context-optimization-design.md
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Detail level for response formatting
|
|
9
|
+
* - minimal: Only essential information (lowest tokens)
|
|
10
|
+
* - summary: Key information with counts and hints (balanced)
|
|
11
|
+
* - detailed: Full information (original behavior)
|
|
12
|
+
*/
|
|
13
|
+
export type DetailLevel = "minimal" | "summary" | "detailed";
|
|
14
|
+
/**
|
|
15
|
+
* Common formatting options
|
|
16
|
+
*/
|
|
17
|
+
import { type PresenterFormat } from "./presenter.js";
|
|
18
|
+
export interface FormatterOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Backwards-compatible alias for detailLevel
|
|
21
|
+
* @deprecated Use detailLevel instead
|
|
22
|
+
*/
|
|
23
|
+
mode?: DetailLevel;
|
|
24
|
+
/**
|
|
25
|
+
* Level of detail in the response
|
|
26
|
+
* @default "summary"
|
|
27
|
+
*/
|
|
28
|
+
detailLevel?: DetailLevel;
|
|
29
|
+
/**
|
|
30
|
+
* Maximum number of items to include in lists
|
|
31
|
+
* @default undefined (no limit)
|
|
32
|
+
*/
|
|
33
|
+
limit?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Include hints about omitted content
|
|
36
|
+
* @default true
|
|
37
|
+
*/
|
|
38
|
+
includeHints?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Structured output format for detailed mode
|
|
41
|
+
* @default "yaml"
|
|
42
|
+
*/
|
|
43
|
+
responseFormat?: PresenterFormat;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Default formatter options
|
|
47
|
+
*/
|
|
48
|
+
export declare const DEFAULT_FORMATTER_OPTIONS: {
|
|
49
|
+
detailLevel: "summary";
|
|
50
|
+
includeHints: true;
|
|
51
|
+
limit: number | undefined;
|
|
52
|
+
responseFormat: PresenterFormat | undefined;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Merge user options with defaults
|
|
56
|
+
*/
|
|
57
|
+
export declare function mergeFormatterOptions(options?: FormatterOptions): {
|
|
58
|
+
detailLevel: DetailLevel;
|
|
59
|
+
limit: number | undefined;
|
|
60
|
+
includeHints: boolean;
|
|
61
|
+
responseFormat?: PresenterFormat;
|
|
62
|
+
};
|
|
63
|
+
interface FormatterMetadata {
|
|
64
|
+
template?: string;
|
|
65
|
+
context?: Record<string, unknown>;
|
|
66
|
+
structured?: unknown;
|
|
67
|
+
}
|
|
68
|
+
export declare function finalizeFormattedText(text: string, opts: {
|
|
69
|
+
responseFormat?: PresenterFormat;
|
|
70
|
+
detailLevel: DetailLevel;
|
|
71
|
+
}, metadata?: FormatterMetadata): string;
|
|
72
|
+
/**
|
|
73
|
+
* Format a hint message for omitted content
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatOmissionHint(totalCount: number, shownCount: number, itemType: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* Truncate array based on limit option
|
|
78
|
+
*/
|
|
79
|
+
export declare function limitArray<T>(items: T[], limit: number | undefined): {
|
|
80
|
+
items: T[];
|
|
81
|
+
truncated: boolean;
|
|
82
|
+
};
|
|
83
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Script Result Formatter
|
|
3
|
+
*
|
|
4
|
+
* Formats Python script execution results with token optimization.
|
|
5
|
+
* Used by EXECUTE_PYTHON_SCRIPT tool.
|
|
6
|
+
*/
|
|
7
|
+
import type { FormatterOptions } from "./responseFormatter.js";
|
|
8
|
+
/**
|
|
9
|
+
* Script execution result structure
|
|
10
|
+
*/
|
|
11
|
+
export interface ScriptResultData {
|
|
12
|
+
success?: boolean;
|
|
13
|
+
data?: {
|
|
14
|
+
result?: unknown;
|
|
15
|
+
output?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
};
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Format script execution result
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatScriptResult(data: ScriptResultData | undefined, scriptSnippet?: string, options?: FormatterOptions): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ToolMetadata } from "../metadata/touchDesignerToolMetadata.js";
|
|
2
|
+
import { type FormatterOptions } from "./responseFormatter.js";
|
|
3
|
+
interface ToolMetadataFormatterOptions extends Partial<FormatterOptions> {
|
|
4
|
+
filter?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function formatToolMetadata(entries: ToolMetadata[], options?: ToolMetadataFormatterOptions): string;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ILogger } from "../../core/logger.js";
|
|
3
|
+
import type { TouchDesignerClient } from "../../tdClient/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Register resource handlers with MCP server
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerTools(server: McpServer, logger: ILogger, tdClient: TouchDesignerClient): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ILogger } from "../../core/logger.js";
|
|
3
|
+
import type { TouchDesignerClient } from "../../tdClient/touchDesignerClient.js";
|
|
4
|
+
import type { ToolNames } from "./index.js";
|
|
5
|
+
export type ToolCategory = "system" | "python" | "nodes" | "classes" | "state";
|
|
6
|
+
/**
|
|
7
|
+
* Single source of truth for a TouchDesigner MCP tool.
|
|
8
|
+
*
|
|
9
|
+
* Both the MCP registration loop (`registerTdTools`) and the
|
|
10
|
+
* `describe_td_tools` manifest (`buildToolMetadata`) are derived from this
|
|
11
|
+
* table, so a tool's description and input parameters can never drift between
|
|
12
|
+
* what is registered and what is documented. Parameter metadata is introspected
|
|
13
|
+
* directly from `schema`, which itself originates from the OpenAPI spec.
|
|
14
|
+
*/
|
|
15
|
+
export interface ToolDefinition {
|
|
16
|
+
/** Registered MCP tool name (also the source for functionName/modulePath). */
|
|
17
|
+
name: ToolNames;
|
|
18
|
+
/** Agent-facing description, used for both registration and the manifest. */
|
|
19
|
+
description: string;
|
|
20
|
+
category: ToolCategory;
|
|
21
|
+
/** Composed Zod schema: OpenAPI-derived params extended with formatting flags. */
|
|
22
|
+
schema: z.ZodObject<z.ZodRawShape>;
|
|
23
|
+
/** Human summary of the return payload (manifest only). */
|
|
24
|
+
returns: string;
|
|
25
|
+
/** Usage example shown in the detailed manifest view (manifest only). */
|
|
26
|
+
example: string;
|
|
27
|
+
notes?: string;
|
|
28
|
+
/** Optional reference comment appended to error output. */
|
|
29
|
+
errorComment?: string;
|
|
30
|
+
/** Executes the tool and returns formatter-ready text. */
|
|
31
|
+
run: (ctx: ToolRunContext) => Promise<string>;
|
|
32
|
+
}
|
|
33
|
+
export interface ToolRunContext {
|
|
34
|
+
params: Record<string, unknown>;
|
|
35
|
+
tdClient: TouchDesignerClient;
|
|
36
|
+
logger: ILogger;
|
|
37
|
+
}
|
|
38
|
+
export declare const TOOL_DEFINITIONS: ToolDefinition[];
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { REFERENCE_COMMENT, TOOL_NAMES } from "../../core/constants.js";
|
|
2
|
+
import { CreateNodeBody, DeleteNodeQueryParams, ExecNodeMethodBody, ExecPythonScriptBody, GetModuleHelpQueryParams, GetNodeDetailQueryParams, GetNodeErrorsQueryParams, GetNodesQueryParams, GetTdPythonClassDetailsParams, UpdateNodeBody, } from "../../gen/mcp/touchDesignerAPI.zod.js";
|
|
3
|
+
import { formatClassDetails, formatClassList, formatCreateNodeResult, formatDeleteNodeResult, formatExecNodeMethodResult, formatModuleHelp, formatNodeDetails, formatNodeErrors, formatNodeList, formatScriptResult, formatTdInfo, formatUpdateNodeResult, } from "./presenter/index.js";
|
|
4
|
+
import { detailOnlyFormattingSchema, formattingOptionsSchema, } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Authoring helper that infers `params` from the tool's schema while erasing to
|
|
7
|
+
* the uniform {@link ToolDefinition} shape for storage in the table.
|
|
8
|
+
*/
|
|
9
|
+
function defineTool(def) {
|
|
10
|
+
// `run` has a narrower param type (z.infer<S>) than ToolDefinition exposes
|
|
11
|
+
// (Record<string, unknown>). Function parameters are contravariant, so a
|
|
12
|
+
// direct `as ToolDefinition` is rejected; the double cast is required. Safe
|
|
13
|
+
// because params are validated by the MCP SDK before reaching run().
|
|
14
|
+
return def;
|
|
15
|
+
}
|
|
16
|
+
export const TOOL_DEFINITIONS = [
|
|
17
|
+
defineTool({
|
|
18
|
+
category: "system",
|
|
19
|
+
description: "Get server information from TouchDesigner",
|
|
20
|
+
example: `import { getTdInfo } from './servers/touchdesigner/getTdInfo';
|
|
21
|
+
|
|
22
|
+
const info = await getTdInfo();
|
|
23
|
+
console.log(\`\${info.server} \${info.version}\`);`,
|
|
24
|
+
name: TOOL_NAMES.GET_TD_INFO,
|
|
25
|
+
returns: "TouchDesigner build metadata (server, version, operating system).",
|
|
26
|
+
run: async ({ params, tdClient }) => {
|
|
27
|
+
const result = await tdClient.getTdInfo();
|
|
28
|
+
if (!result.success) {
|
|
29
|
+
throw result.error;
|
|
30
|
+
}
|
|
31
|
+
return formatTdInfo(result.data, {
|
|
32
|
+
detailLevel: params.detailLevel ?? "summary",
|
|
33
|
+
responseFormat: params.responseFormat,
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
schema: detailOnlyFormattingSchema,
|
|
37
|
+
}),
|
|
38
|
+
defineTool({
|
|
39
|
+
category: "python",
|
|
40
|
+
description: "Execute a Python script in TouchDesigner (detailLevel=minimal|summary|detailed, responseFormat=json|yaml|markdown)",
|
|
41
|
+
example: `import { executePythonScript } from './servers/touchdesigner/executePythonScript';
|
|
42
|
+
|
|
43
|
+
await executePythonScript({
|
|
44
|
+
script: "op('/project1/text1').par.text = 'Hello MCP'",
|
|
45
|
+
});`,
|
|
46
|
+
name: TOOL_NAMES.EXECUTE_PYTHON_SCRIPT,
|
|
47
|
+
notes: "Wrap long-running scripts with logging so the agent can stream intermediate checkpoints.",
|
|
48
|
+
returns: "Result payload that mirrors `result` from the executed script (if set).",
|
|
49
|
+
run: async ({ params, tdClient, logger }) => {
|
|
50
|
+
const { detailLevel, responseFormat, ...scriptParams } = params;
|
|
51
|
+
logger.sendLog({
|
|
52
|
+
data: `Executing script: ${scriptParams.script}`,
|
|
53
|
+
level: "debug",
|
|
54
|
+
});
|
|
55
|
+
const result = await tdClient.execPythonScript(scriptParams);
|
|
56
|
+
if (!result.success) {
|
|
57
|
+
throw result.error;
|
|
58
|
+
}
|
|
59
|
+
return formatScriptResult(result, scriptParams.script, {
|
|
60
|
+
detailLevel: detailLevel ?? "summary",
|
|
61
|
+
responseFormat,
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
schema: ExecPythonScriptBody.extend(detailOnlyFormattingSchema.shape),
|
|
65
|
+
}),
|
|
66
|
+
defineTool({
|
|
67
|
+
category: "nodes",
|
|
68
|
+
description: "List nodes under a path with token-optimized output (detailLevel+limit supported)",
|
|
69
|
+
errorComment: REFERENCE_COMMENT,
|
|
70
|
+
example: `import { getTdNodes } from './servers/touchdesigner/getTdNodes';
|
|
71
|
+
|
|
72
|
+
const nodes = await getTdNodes({
|
|
73
|
+
parentPath: '/project1',
|
|
74
|
+
pattern: 'geo*',
|
|
75
|
+
});
|
|
76
|
+
console.log(nodes.nodes?.map(node => node.path));`,
|
|
77
|
+
name: TOOL_NAMES.GET_TD_NODES,
|
|
78
|
+
returns: "Set of nodes (id, opType, name, path, optional properties) under parentPath.",
|
|
79
|
+
run: async ({ params, tdClient }) => {
|
|
80
|
+
const { detailLevel, limit, responseFormat, ...queryParams } = params;
|
|
81
|
+
const result = await tdClient.getNodes(queryParams);
|
|
82
|
+
if (!result.success) {
|
|
83
|
+
throw result.error;
|
|
84
|
+
}
|
|
85
|
+
const fallbackMode = queryParams.includeProperties
|
|
86
|
+
? "detailed"
|
|
87
|
+
: "summary";
|
|
88
|
+
return formatNodeList(result.data, {
|
|
89
|
+
detailLevel: detailLevel ?? fallbackMode,
|
|
90
|
+
limit,
|
|
91
|
+
responseFormat,
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
schema: GetNodesQueryParams.extend(formattingOptionsSchema.shape),
|
|
95
|
+
}),
|
|
96
|
+
defineTool({
|
|
97
|
+
category: "nodes",
|
|
98
|
+
description: "Get node parameters with concise/detailed formatting (detailLevel+limit supported)",
|
|
99
|
+
errorComment: REFERENCE_COMMENT,
|
|
100
|
+
example: `import { getTdNodeParameters } from './servers/touchdesigner/getTdNodeParameters';
|
|
101
|
+
|
|
102
|
+
const node = await getTdNodeParameters({ nodePath: '/project1/text1' });
|
|
103
|
+
console.log(node.properties?.Text);`,
|
|
104
|
+
name: TOOL_NAMES.GET_TD_NODE_PARAMETERS,
|
|
105
|
+
returns: "Full node record with parameters, paths, and metadata.",
|
|
106
|
+
run: async ({ params, tdClient }) => {
|
|
107
|
+
const { detailLevel, limit, responseFormat, ...queryParams } = params;
|
|
108
|
+
const result = await tdClient.getNodeDetail(queryParams);
|
|
109
|
+
if (!result.success) {
|
|
110
|
+
throw result.error;
|
|
111
|
+
}
|
|
112
|
+
return formatNodeDetails(result.data, {
|
|
113
|
+
detailLevel: detailLevel ?? "summary",
|
|
114
|
+
limit,
|
|
115
|
+
responseFormat,
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
schema: GetNodeDetailQueryParams.extend(formattingOptionsSchema.shape),
|
|
119
|
+
}),
|
|
120
|
+
defineTool({
|
|
121
|
+
category: "nodes",
|
|
122
|
+
description: "Check node and descendant errors reported by TouchDesigner",
|
|
123
|
+
errorComment: REFERENCE_COMMENT,
|
|
124
|
+
example: `import { getTdNodeErrors } from './servers/touchdesigner/getTdNodeErrors';
|
|
125
|
+
|
|
126
|
+
const report = await getTdNodeErrors({
|
|
127
|
+
nodePath: '/project1/text1',
|
|
128
|
+
});
|
|
129
|
+
if (report.hasErrors) {
|
|
130
|
+
console.log(report.errors?.map(err => err.message));
|
|
131
|
+
}`,
|
|
132
|
+
name: TOOL_NAMES.GET_TD_NODE_ERRORS,
|
|
133
|
+
returns: "Error report outlining offending nodes, messages, and counts.",
|
|
134
|
+
run: async ({ params, tdClient }) => {
|
|
135
|
+
const { detailLevel, limit, responseFormat, ...queryParams } = params;
|
|
136
|
+
const result = await tdClient.getNodeErrors(queryParams);
|
|
137
|
+
if (!result.success) {
|
|
138
|
+
throw result.error;
|
|
139
|
+
}
|
|
140
|
+
return formatNodeErrors(result.data, {
|
|
141
|
+
detailLevel: detailLevel ?? "summary",
|
|
142
|
+
limit,
|
|
143
|
+
responseFormat,
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
schema: GetNodeErrorsQueryParams.extend(formattingOptionsSchema.shape),
|
|
147
|
+
}),
|
|
148
|
+
defineTool({
|
|
149
|
+
category: "nodes",
|
|
150
|
+
description: "Create a new node in TouchDesigner",
|
|
151
|
+
errorComment: REFERENCE_COMMENT,
|
|
152
|
+
example: `import { createTdNode } from './servers/touchdesigner/createTdNode';
|
|
153
|
+
|
|
154
|
+
const created = await createTdNode({
|
|
155
|
+
parentPath: '/project1',
|
|
156
|
+
nodeType: 'textTOP',
|
|
157
|
+
nodeName: 'title',
|
|
158
|
+
});
|
|
159
|
+
console.log(created.result?.path);`,
|
|
160
|
+
name: TOOL_NAMES.CREATE_TD_NODE,
|
|
161
|
+
returns: "Created node metadata including resolved path and properties.",
|
|
162
|
+
run: async ({ params, tdClient }) => {
|
|
163
|
+
const { detailLevel, responseFormat, ...createParams } = params;
|
|
164
|
+
const result = await tdClient.createNode(createParams);
|
|
165
|
+
if (!result.success) {
|
|
166
|
+
throw result.error;
|
|
167
|
+
}
|
|
168
|
+
return formatCreateNodeResult(result.data, {
|
|
169
|
+
detailLevel: detailLevel ?? "summary",
|
|
170
|
+
responseFormat,
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
schema: CreateNodeBody.extend(detailOnlyFormattingSchema.shape),
|
|
174
|
+
}),
|
|
175
|
+
defineTool({
|
|
176
|
+
category: "nodes",
|
|
177
|
+
description: "Update parameters of a specific node in TouchDesigner",
|
|
178
|
+
errorComment: REFERENCE_COMMENT,
|
|
179
|
+
example: `import { updateTdNodeParameters } from './servers/touchdesigner/updateTdNodeParameters';
|
|
180
|
+
|
|
181
|
+
await updateTdNodeParameters({
|
|
182
|
+
nodePath: '/project1/text1',
|
|
183
|
+
properties: { text: 'Hello TouchDesigner' },
|
|
184
|
+
});`,
|
|
185
|
+
name: TOOL_NAMES.UPDATE_TD_NODE_PARAMETERS,
|
|
186
|
+
returns: "Lists of updated vs failed parameters so the agent can retry selectively.",
|
|
187
|
+
run: async ({ params, tdClient }) => {
|
|
188
|
+
const { detailLevel, responseFormat, ...updateParams } = params;
|
|
189
|
+
const result = await tdClient.updateNode(updateParams);
|
|
190
|
+
if (!result.success) {
|
|
191
|
+
throw result.error;
|
|
192
|
+
}
|
|
193
|
+
return formatUpdateNodeResult(result.data, {
|
|
194
|
+
detailLevel: detailLevel ?? "summary",
|
|
195
|
+
responseFormat,
|
|
196
|
+
});
|
|
197
|
+
},
|
|
198
|
+
schema: UpdateNodeBody.extend(detailOnlyFormattingSchema.shape),
|
|
199
|
+
}),
|
|
200
|
+
defineTool({
|
|
201
|
+
category: "nodes",
|
|
202
|
+
description: "Delete an existing node in TouchDesigner",
|
|
203
|
+
errorComment: REFERENCE_COMMENT,
|
|
204
|
+
example: `import { deleteTdNode } from './servers/touchdesigner/deleteTdNode';
|
|
205
|
+
|
|
206
|
+
const result = await deleteTdNode({ nodePath: '/project1/tmp1' });
|
|
207
|
+
console.log(result.deleted);`,
|
|
208
|
+
name: TOOL_NAMES.DELETE_TD_NODE,
|
|
209
|
+
returns: "Deletion status plus previous node metadata when available.",
|
|
210
|
+
run: async ({ params, tdClient }) => {
|
|
211
|
+
const { detailLevel, responseFormat, ...deleteParams } = params;
|
|
212
|
+
const result = await tdClient.deleteNode(deleteParams);
|
|
213
|
+
if (!result.success) {
|
|
214
|
+
throw result.error;
|
|
215
|
+
}
|
|
216
|
+
return formatDeleteNodeResult(result.data, {
|
|
217
|
+
detailLevel: detailLevel ?? "summary",
|
|
218
|
+
responseFormat,
|
|
219
|
+
});
|
|
220
|
+
},
|
|
221
|
+
schema: DeleteNodeQueryParams.extend(detailOnlyFormattingSchema.shape),
|
|
222
|
+
}),
|
|
223
|
+
defineTool({
|
|
224
|
+
category: "nodes",
|
|
225
|
+
description: "Execute a method on a specific node in TouchDesigner",
|
|
226
|
+
errorComment: REFERENCE_COMMENT,
|
|
227
|
+
example: `import { execNodeMethod } from './servers/touchdesigner/execNodeMethod';
|
|
228
|
+
|
|
229
|
+
const renderStatus = await execNodeMethod({
|
|
230
|
+
nodePath: '/project1/render1',
|
|
231
|
+
method: 'par',
|
|
232
|
+
kwargs: { enable: true },
|
|
233
|
+
});
|
|
234
|
+
console.log(renderStatus.result);`,
|
|
235
|
+
name: TOOL_NAMES.EXECUTE_NODE_METHOD,
|
|
236
|
+
returns: "Raw method return payload including any serializable values.",
|
|
237
|
+
run: async ({ params, tdClient }) => {
|
|
238
|
+
const { detailLevel, responseFormat, ...execParams } = params;
|
|
239
|
+
const { nodePath, method, args, kwargs } = execParams;
|
|
240
|
+
const result = await tdClient.execNodeMethod(execParams);
|
|
241
|
+
if (!result.success) {
|
|
242
|
+
throw result.error;
|
|
243
|
+
}
|
|
244
|
+
return formatExecNodeMethodResult(result.data, { args, kwargs, method, nodePath }, { detailLevel: detailLevel ?? "summary", responseFormat });
|
|
245
|
+
},
|
|
246
|
+
schema: ExecNodeMethodBody.extend(detailOnlyFormattingSchema.shape),
|
|
247
|
+
}),
|
|
248
|
+
defineTool({
|
|
249
|
+
category: "classes",
|
|
250
|
+
description: "List TouchDesigner Python classes/modules (detailLevel+limit supported)",
|
|
251
|
+
errorComment: REFERENCE_COMMENT,
|
|
252
|
+
example: `import { getTdClasses } from './servers/touchdesigner/getTdClasses';
|
|
253
|
+
|
|
254
|
+
const classes = await getTdClasses({ limit: 20 });
|
|
255
|
+
console.log(classes.classes?.map(cls => cls.name));`,
|
|
256
|
+
name: TOOL_NAMES.GET_TD_CLASSES,
|
|
257
|
+
returns: "Python class catalogue with names, types, and optional summaries.",
|
|
258
|
+
run: async ({ params, tdClient }) => {
|
|
259
|
+
const result = await tdClient.getClasses();
|
|
260
|
+
if (!result.success) {
|
|
261
|
+
throw result.error;
|
|
262
|
+
}
|
|
263
|
+
return formatClassList(result.data, {
|
|
264
|
+
detailLevel: params.detailLevel ?? "summary",
|
|
265
|
+
limit: params.limit ?? 50,
|
|
266
|
+
responseFormat: params.responseFormat,
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
schema: formattingOptionsSchema,
|
|
270
|
+
}),
|
|
271
|
+
defineTool({
|
|
272
|
+
category: "classes",
|
|
273
|
+
description: "Get information about a TouchDesigner class/module (detailLevel+limit supported)",
|
|
274
|
+
errorComment: REFERENCE_COMMENT,
|
|
275
|
+
example: `import { getTdClassDetails } from './servers/touchdesigner/getTdClassDetails';
|
|
276
|
+
|
|
277
|
+
const textTop = await getTdClassDetails({ className: 'textTOP' });
|
|
278
|
+
console.log(textTop.methods?.length);`,
|
|
279
|
+
name: TOOL_NAMES.GET_TD_CLASS_DETAILS,
|
|
280
|
+
returns: "Deep description of a Python class including methods and properties.",
|
|
281
|
+
run: async ({ params, tdClient }) => {
|
|
282
|
+
const { className, detailLevel, limit, responseFormat } = params;
|
|
283
|
+
const result = await tdClient.getClassDetails(className);
|
|
284
|
+
if (!result.success) {
|
|
285
|
+
throw result.error;
|
|
286
|
+
}
|
|
287
|
+
return formatClassDetails(result.data, {
|
|
288
|
+
detailLevel: detailLevel ?? "summary",
|
|
289
|
+
limit: limit ?? 30,
|
|
290
|
+
responseFormat,
|
|
291
|
+
});
|
|
292
|
+
},
|
|
293
|
+
schema: GetTdPythonClassDetailsParams.extend(formattingOptionsSchema.shape),
|
|
294
|
+
}),
|
|
295
|
+
defineTool({
|
|
296
|
+
category: "classes",
|
|
297
|
+
description: "Retrieve Python help() text for a TouchDesigner module or class",
|
|
298
|
+
example: `import { getTdModuleHelp } from './servers/touchdesigner/getTdModuleHelp';
|
|
299
|
+
|
|
300
|
+
const docs = await getTdModuleHelp({ moduleName: 'noiseCHOP' });
|
|
301
|
+
console.log(docs.helpText?.slice(0, 200));`,
|
|
302
|
+
name: TOOL_NAMES.GET_TD_MODULE_HELP,
|
|
303
|
+
returns: "Captured Python help() output with formatter context.",
|
|
304
|
+
run: async ({ params, tdClient }) => {
|
|
305
|
+
const { detailLevel, moduleName, responseFormat } = params;
|
|
306
|
+
const result = await tdClient.getModuleHelp({ moduleName });
|
|
307
|
+
if (!result.success) {
|
|
308
|
+
throw result.error;
|
|
309
|
+
}
|
|
310
|
+
return formatModuleHelp(result.data, {
|
|
311
|
+
detailLevel: detailLevel ?? "summary",
|
|
312
|
+
responseFormat,
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
schema: GetModuleHelpQueryParams.extend(detailOnlyFormattingSchema.shape),
|
|
316
|
+
}),
|
|
317
|
+
];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Shared Zod schemas for MCP tool formatting parameters.
|
|
4
|
+
* These stay on the TypeScript side only and are not sent to TouchDesigner.
|
|
5
|
+
*/
|
|
6
|
+
export declare const detailLevelSchema: z.ZodEnum<{
|
|
7
|
+
detailed: "detailed";
|
|
8
|
+
minimal: "minimal";
|
|
9
|
+
summary: "summary";
|
|
10
|
+
}>;
|
|
11
|
+
export declare const limitSchema: z.ZodNumber;
|
|
12
|
+
export declare const presenterFormatSchema: z.ZodEnum<{
|
|
13
|
+
json: "json";
|
|
14
|
+
yaml: "yaml";
|
|
15
|
+
markdown: "markdown";
|
|
16
|
+
}>;
|
|
17
|
+
export declare const detailOnlyFormattingSchema: z.ZodObject<{
|
|
18
|
+
detailLevel: z.ZodOptional<z.ZodEnum<{
|
|
19
|
+
detailed: "detailed";
|
|
20
|
+
minimal: "minimal";
|
|
21
|
+
summary: "summary";
|
|
22
|
+
}>>;
|
|
23
|
+
responseFormat: z.ZodOptional<z.ZodEnum<{
|
|
24
|
+
json: "json";
|
|
25
|
+
yaml: "yaml";
|
|
26
|
+
markdown: "markdown";
|
|
27
|
+
}>>;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
export declare const formattingOptionsSchema: z.ZodObject<{
|
|
30
|
+
detailLevel: z.ZodOptional<z.ZodEnum<{
|
|
31
|
+
detailed: "detailed";
|
|
32
|
+
minimal: "minimal";
|
|
33
|
+
summary: "summary";
|
|
34
|
+
}>>;
|
|
35
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
36
|
+
responseFormat: z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
json: "json";
|
|
38
|
+
yaml: "yaml";
|
|
39
|
+
markdown: "markdown";
|
|
40
|
+
}>>;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
export type DetailOnlyFormattingParams = z.input<typeof detailOnlyFormattingSchema>;
|
|
43
|
+
export type FormattingOptionsParams = z.input<typeof formattingOptionsSchema>;
|
|
File without changes
|