touchdesigner-mcp-server
Version:
MCP server for TouchDesigner
119 lines (118 loc) • 4.4 kB
JavaScript
import { finalizeFormattedText, mergeFormatterOptions, } from "./responseFormatter.js";
export function formatToolMetadata(entries, options) {
const { detailLevel, responseFormat } = mergeFormatterOptions(options);
if (entries.length === 0) {
return finalizeFormattedText("No tools matched the requested criteria.", { detailLevel, responseFormat }, {
context: { filter: options?.filter, totalTools: 0 },
});
}
const sortedEntries = [...entries].sort((a, b) => a.modulePath.localeCompare(b.modulePath));
const structured = sortedEntries.map((entry) => ({
category: entry.category,
description: entry.description,
functionName: entry.functionName,
modulePath: entry.modulePath,
notes: entry.notes,
parameters: entry.parameters,
returns: entry.returns,
tool: entry.tool,
}));
const text = buildText(sortedEntries, detailLevel);
return finalizeFormattedText(text, { detailLevel, responseFormat }, {
context: {
filter: options?.filter,
totalTools: sortedEntries.length,
},
structured,
template: detailLevel === "detailed" ? "detailedPayload" : undefined,
});
}
function buildText(entries, detailLevel) {
switch (detailLevel) {
case "minimal":
return formatTree(entries);
case "detailed":
return formatDetailed(entries);
default:
return formatSummary(entries);
}
}
function formatTree(entries) {
const segmentsList = entries.map((entry) => entry.modulePath.replace(/^\.\//, "").split("/"));
const commonSegments = findCommonDirectorySegments(segmentsList);
const basePath = commonSegments.length > 0 ? `${commonSegments.join("/")}/` : "./";
const relativePaths = entries.map((entry, index) => {
const segments = segmentsList[index];
const relative = segments.slice(commonSegments.length).join("/");
const connector = index === entries.length - 1 ? "└──" : "├──";
return `${connector} ${relative} — ${entry.description}`;
});
return ["Filesystem blueprint:", basePath, ...relativePaths].join("\n");
}
function formatSummary(entries) {
return entries
.map((entry) => {
const params = entry.parameters.length > 0
? entry.parameters
.map((param) => `- ${param.name}${param.required ? "" : "?"} (${param.type})${param.description ? ` — ${param.description}` : ""}`)
.join("\n")
: "- (no parameters)";
return `${entry.functionName} (${entry.modulePath})
Tool: ${entry.tool}
Category: ${entry.category}
Description: ${entry.description}
Parameters:
${params}
Returns: ${entry.returns}`;
})
.join("\n\n");
}
function formatDetailed(entries) {
return entries
.map((entry) => {
const params = entry.parameters.length > 0
? entry.parameters
.map((param) => `- ${param.name}${param.required ? "" : "?"} (${param.type})${param.description ? ` — ${param.description}` : ""}`)
.join("\n")
: "- (no parameters)";
const sections = [
`### ${entry.functionName} (${entry.tool})`,
`Module: ${entry.modulePath}`,
`Category: ${entry.category}`,
`Description: ${entry.description}`,
"Parameters:",
params,
`Returns: ${entry.returns}`,
"Example:",
"```ts",
entry.example.trim(),
"```",
];
if (entry.notes) {
sections.push(`Notes: ${entry.notes}`);
}
return sections.join("\n");
})
.join("\n\n---\n\n");
}
function findCommonDirectorySegments(segmentsList) {
if (segmentsList.length === 0) {
return [];
}
const directories = segmentsList.map((parts) => parts.slice(0, Math.max(parts.length - 1, 0)));
let prefix = directories[0];
for (let i = 1; i < directories.length; i += 1) {
const current = directories[i];
let j = 0;
while (j < prefix.length &&
j < current.length &&
prefix[j] === current[j]) {
j += 1;
}
prefix = prefix.slice(0, j);
if (prefix.length === 0) {
break;
}
}
return prefix;
}