Skip to main content
Glama

set_multiple_annotations

Apply multiple annotations simultaneously to Figma design elements to document components, provide feedback, or categorize sections within a node.

Instructions

Set multiple annotations parallelly in a node

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nodeIdYesThe ID of the node containing the elements to annotate
annotationsYesArray of annotations to apply

Implementation Reference

  • Registration and handler implementation of the MCP tool 'set_multiple_annotations'. The handler validates input using Zod schema, processes annotations in batches via the Figma plugin using sendCommandToFigma, and provides progress feedback.
    server.tool( "set_multiple_annotations", "Set multiple annotations parallelly in a node", { nodeId: z .string() .describe("The ID of the node containing the elements 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 in markdown format"), categoryId: z.string().optional().describe("The ID of the annotation category"), annotationId: z.string().optional().describe("The ID of the annotation to update (if updating existing annotation)"), properties: z.array(z.object({ type: z.string() })).optional().describe("Additional properties for the annotation") }) ) .describe("Array of annotations to apply"), }, async ({ nodeId, annotations }, extra) => { try { if (!annotations || annotations.length === 0) { return { content: [ { type: "text", text: "No annotations provided", }, ], }; } // Initial response to indicate we're starting the process const initialStatus = { type: "text" as const, text: `Starting annotation process for ${annotations.length} nodes. This will be processed in batches of 5...`, }; // Track overall progress let totalProcessed = 0; const totalToProcess = annotations.length; // Use the plugin's set_multiple_annotations function with chunking const result = await sendCommandToFigma("set_multiple_annotations", { nodeId, annotations, }); // Cast the result to a specific type to work with it safely interface AnnotationResult { success: boolean; nodeId: string; annotationsApplied?: number; annotationsFailed?: number; totalAnnotations?: number; completedInChunks?: number; results?: Array<{ success: boolean; nodeId: string; error?: string; annotationId?: string; }>; } const typedResult = result as AnnotationResult; // Format the results for display const success = typedResult.annotationsApplied && typedResult.annotationsApplied > 0; const progressText = ` Annotation process completed: - ${typedResult.annotationsApplied || 0} of ${totalToProcess} successfully applied - ${typedResult.annotationsFailed || 0} failed - Processed in ${typedResult.completedInChunks || 1} batches `; // Detailed results const detailedResults = typedResult.results || []; const failedResults = detailedResults.filter(item => !item.success); // Create the detailed part of the response let detailedResponse = ""; if (failedResults.length > 0) { detailedResponse = `\n\nNodes that failed:\n${failedResults.map(item => `- ${item.nodeId}: ${item.error || "Unknown error"}` ).join('\n')}`; } return { content: [ initialStatus, { type: "text" as const, text: progressText + detailedResponse, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error setting multiple annotations: ${error instanceof Error ? error.message : String(error) }`, }, ], }; } } );
  • TypeScript interface defining the parameters for set_multiple_annotations command sent to Figma plugin.
    interface SetMultipleAnnotationsParams { nodeId: string; annotations: Array<{ nodeId: string; labelMarkdown: string; categoryId?: string; annotationId?: string; properties?: Array<{ type: string }>; }>; }
  • Zod schema for input validation of the MCP tool 'set_multiple_annotations'.
    nodeId: z .string() .describe("The ID of the node containing the elements 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 in markdown format"), categoryId: z.string().optional().describe("The ID of the annotation category"), annotationId: z.string().optional().describe("The ID of the annotation to update (if updating existing annotation)"), properties: z.array(z.object({ type: z.string() })).optional().describe("Additional properties for the annotation") }) ) .describe("Array of annotations to apply"), }, async ({ nodeId, annotations }, extra) => { try { if (!annotations || annotations.length === 0) { return { content: [ { type: "text", text: "No annotations provided", }, ], }; } // Initial response to indicate we're starting the process const initialStatus = { type: "text" as const, text: `Starting annotation process for ${annotations.length} nodes. This will be processed in batches of 5...`, }; // Track overall progress let totalProcessed = 0; const totalToProcess = annotations.length; // Use the plugin's set_multiple_annotations function with chunking const result = await sendCommandToFigma("set_multiple_annotations", { nodeId, annotations, }); // Cast the result to a specific type to work with it safely interface AnnotationResult { success: boolean; nodeId: string; annotationsApplied?: number; annotationsFailed?: number; totalAnnotations?: number; completedInChunks?: number; results?: Array<{ success: boolean; nodeId: string; error?: string; annotationId?: string; }>; } const typedResult = result as AnnotationResult; // Format the results for display const success = typedResult.annotationsApplied && typedResult.annotationsApplied > 0; const progressText = ` Annotation process completed: - ${typedResult.annotationsApplied || 0} of ${totalToProcess} successfully applied - ${typedResult.annotationsFailed || 0} failed - Processed in ${typedResult.completedInChunks || 1} batches `; // Detailed results const detailedResults = typedResult.results || []; const failedResults = detailedResults.filter(item => !item.success); // Create the detailed part of the response let detailedResponse = ""; if (failedResults.length > 0) { detailedResponse = `\n\nNodes that failed:\n${failedResults.map(item => `- ${item.nodeId}: ${item.error || "Unknown error"}` ).join('\n')}`; } return { content: [ initialStatus, { type: "text" as const, text: progressText + detailedResponse, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error setting multiple annotations: ${error instanceof Error ? error.message : String(error) }`, }, ], }; } }
  • The core handler function that executes the tool logic by forwarding the annotations to the Figma plugin via WebSocket (sendCommandToFigma), handles batch processing feedback, and formats the response with success metrics.
    async ({ nodeId, annotations }, extra) => { try { if (!annotations || annotations.length === 0) { return { content: [ { type: "text", text: "No annotations provided", }, ], }; } // Initial response to indicate we're starting the process const initialStatus = { type: "text" as const, text: `Starting annotation process for ${annotations.length} nodes. This will be processed in batches of 5...`, }; // Track overall progress let totalProcessed = 0; const totalToProcess = annotations.length; // Use the plugin's set_multiple_annotations function with chunking const result = await sendCommandToFigma("set_multiple_annotations", { nodeId, annotations, }); // Cast the result to a specific type to work with it safely interface AnnotationResult { success: boolean; nodeId: string; annotationsApplied?: number; annotationsFailed?: number; totalAnnotations?: number; completedInChunks?: number; results?: Array<{ success: boolean; nodeId: string; error?: string; annotationId?: string; }>; } const typedResult = result as AnnotationResult; // Format the results for display const success = typedResult.annotationsApplied && typedResult.annotationsApplied > 0; const progressText = ` Annotation process completed: - ${typedResult.annotationsApplied || 0} of ${totalToProcess} successfully applied - ${typedResult.annotationsFailed || 0} failed - Processed in ${typedResult.completedInChunks || 1} batches `; // Detailed results const detailedResults = typedResult.results || []; const failedResults = detailedResults.filter(item => !item.success); // Create the detailed part of the response let detailedResponse = ""; if (failedResults.length > 0) { detailedResponse = `\n\nNodes that failed:\n${failedResults.map(item => `- ${item.nodeId}: ${item.error || "Unknown error"}` ).join('\n')}`; } return { content: [ initialStatus, { type: "text" as const, text: progressText + detailedResponse, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error setting multiple annotations: ${error instanceof Error ? error.message : String(error) }`, }, ], }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pipethedev/Talk-to-Figma-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server