import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { sendCommandToFigma } from "../communication";
import { logger } from "../logger";
/**
* Register annotation-related MCP tools
*/
export function registerAnnotationTools(server: McpServer): void {
// Get Annotations
server.tool(
"get_annotations",
"Get all annotations in the current document or specific node",
{
nodeId: z
.string()
.optional()
.describe("Node ID to get annotations for specific node"),
includeCategories: z
.boolean()
.optional()
.default(true)
.describe("Whether to include category information"),
},
async ({ nodeId, includeCategories }) => {
try {
const result = await sendCommandToFigma("get_annotations", {
nodeId,
includeCategories,
});
return {
content: [
{
type: "text",
text: JSON.stringify(result),
},
],
};
} catch (error) {
logger.error("Error getting annotations", error);
return {
content: [
{
type: "text",
text: `Error getting annotations: ${
error instanceof Error ? error.message : String(error)
}`,
},
],
};
}
},
);
// Set Annotation
server.tool(
"set_annotation",
"Create or update an annotation on a node",
{
nodeId: z.string().describe("The ID of the node to annotate"),
annotationId: z
.string()
.optional()
.describe("The ID of the annotation to update (if updating existing)"),
labelMarkdown: z
.string()
.describe("The annotation text in markdown format"),
categoryId: z
.string()
.optional()
.describe("The ID of the annotation category"),
properties: z
.array(
z.object({
type: z.string(),
}),
)
.optional()
.describe("Additional properties for the annotation"),
},
async ({ nodeId, annotationId, labelMarkdown, categoryId, properties }) => {
try {
const result = await sendCommandToFigma<{
success: boolean;
annotationId: string;
}>("set_annotation", {
nodeId,
annotationId,
labelMarkdown,
categoryId,
properties,
});
return {
content: [
{
type: "text",
text: result.success
? `Annotation ${annotationId ? "updated" : "created"} with ID: ${result.annotationId}`
: "Failed to set annotation",
},
],
};
} catch (error) {
logger.error("Error setting annotation", error);
return {
content: [
{
type: "text",
text: `Error setting annotation: ${
error instanceof Error ? error.message : String(error)
}`,
},
],
};
}
},
);
// Set Multiple Annotations
server.tool(
"set_multiple_annotations",
"Create or update multiple annotations at once",
{
nodeId: z
.string()
.describe("The root node ID containing the nodes to annotate"),
annotations: z
.array(
z.object({
nodeId: z.string().describe("The ID of the node to annotate"),
labelMarkdown: z.string().describe("The annotation text"),
categoryId: z.string().optional(),
annotationId: z.string().optional(),
properties: z.array(z.object({ type: z.string() })).optional(),
}),
)
.describe("Array of annotations to create/update"),
},
async ({ nodeId, annotations }) => {
try {
const result = await sendCommandToFigma<{
success: boolean;
createdCount: number;
updatedCount: number;
}>("set_multiple_annotations", { nodeId, annotations });
return {
content: [
{
type: "text",
text: `Created ${result.createdCount} annotations, updated ${result.updatedCount} annotations`,
},
],
};
} catch (error) {
logger.error("Error setting multiple annotations", error);
return {
content: [
{
type: "text",
text: `Error setting multiple annotations: ${
error instanceof Error ? error.message : String(error)
}`,
},
],
};
}
},
);
}