touchdesigner-mcp-server
Version:
MCP server for TouchDesigner
215 lines (214 loc) • 8.44 kB
JavaScript
import { REFERENCE_COMMENT, TOOL_NAMES } from "../../../core/constants.js";
import { handleToolError } from "../../../core/errorHandling.js";
import { createNodeBody, deleteNodeQueryParams, execNodeMethodBody, execPythonScriptBody, getNodeDetailQueryParams, getNodesQueryParams, getTdPythonClassDetailsParams, updateNodeBody, } from "../../../gen/mcp/touchDesignerAPI.zod.js";
export function registerTdTools(server, logger, tdClient) {
server.tool(TOOL_NAMES.GET_TD_INFO, "Get server information from TouchDesigner", async () => {
try {
const result = await tdClient.getTdInfo();
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Server information: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.GET_TD_INFO);
}
});
server.tool(TOOL_NAMES.EXECUTE_PYTHON_SCRIPT, "Execute Python script directly in TouchDesigner", execPythonScriptBody.strict().shape, async (params) => {
try {
const { script } = params;
logger.debug(`Executing script: ${script}`);
const result = await tdClient.execPythonScript(params);
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Script executed successfully. Result: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.EXECUTE_PYTHON_SCRIPT);
}
});
server.tool(TOOL_NAMES.CREATE_TD_NODE, "Create a new node in TouchDesigner", createNodeBody.strict().shape, async (params) => {
try {
const { parentPath, nodeType, nodeName } = params;
const result = await tdClient.createNode({
parentPath,
nodeType,
nodeName,
});
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Node created successfully: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.CREATE_TD_NODE, REFERENCE_COMMENT);
}
});
server.tool(TOOL_NAMES.DELETE_TD_NODE, "Delete an existing node in TouchDesigner", deleteNodeQueryParams.strict().shape, async (params) => {
try {
const result = await tdClient.deleteNode(params);
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Node deleted successfully: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.DELETE_TD_NODE, REFERENCE_COMMENT);
}
});
server.tool(TOOL_NAMES.GET_TD_NODES, "Get all nodes in the parent path", getNodesQueryParams.strict().shape, async (params) => {
try {
const result = await tdClient.getNodes(params);
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Project nodes retrieved: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.GET_TD_NODES, REFERENCE_COMMENT);
}
});
server.tool(TOOL_NAMES.GET_TD_NODE_PARAMETERS, "Get parameters of a specific node in TouchDesigner", getNodeDetailQueryParams.strict().shape, async (params) => {
try {
const { nodePath } = params;
const result = await tdClient.getNodeDetail(params);
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Node parameters for node at path ${nodePath}: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.GET_TD_NODE_PARAMETERS, REFERENCE_COMMENT);
}
});
server.tool(TOOL_NAMES.UPDATE_TD_NODE_PARAMETERS, "Update parameters of a specific node in TouchDesigner", updateNodeBody.strict().shape, async (params) => {
try {
const result = await tdClient.updateNode(params);
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Node parameters updated successfully: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.UPDATE_TD_NODE_PARAMETERS, REFERENCE_COMMENT);
}
});
server.tool(TOOL_NAMES.EXECUTE_NODE_METHOD, "Execute a method on a specific node in TouchDesigner", execNodeMethodBody.strict().shape, async (params) => {
try {
const { nodePath, method, args } = params;
const result = await tdClient.execNodeMethod(params);
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `op('${nodePath}').${method}(${args?.map((v) => `"${v}"`).join(",")}${params.kwargs
? Object.entries(params.kwargs)
.map(([key, value]) => `${key}=${JSON.stringify(value)}`)
.join(", ")
: ""})`,
},
{
type: "text",
text: JSON.stringify(result, null, 2),
},
],
};
}
catch (error) {
logger.error(error);
return handleToolError(error, logger, TOOL_NAMES.EXECUTE_NODE_METHOD, REFERENCE_COMMENT);
}
});
server.tool(TOOL_NAMES.GET_TD_CLASSES, "Get list of classes and modules in TouchDesigner", async () => {
try {
const result = await tdClient.getClasses();
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `TouchDesigner classes list: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.GET_TD_CLASSES, REFERENCE_COMMENT);
}
});
server.tool(TOOL_NAMES.GET_TD_CLASS_DETAILS, "Get detailed information about a specific TouchDesigner class or module", getTdPythonClassDetailsParams.strict().shape, async (params) => {
try {
const { className } = params;
const result = await tdClient.getClassDetails(className);
if (!result.success) {
throw result.error;
}
return {
content: [
{
type: "text",
text: `Details for ${className}: ${JSON.stringify(result, null, 2)}`,
},
],
};
}
catch (error) {
return handleToolError(error, logger, TOOL_NAMES.GET_TD_CLASS_DETAILS, REFERENCE_COMMENT);
}
});
}