delete_multiple_nodes
Remove multiple design elements in Figma simultaneously using the Cursor Talk to Figma MCP integration, streamlining bulk deletion tasks in your workflow.
Instructions
Delete multiple nodes from Figma at once
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {},
"type": "object"
}
Implementation Reference
- src/cursor_mcp_plugin/code.js:2491-2691 (handler)Core handler function in Figma plugin that implements delete_multiple_nodes by fetching nodes by ID, chunking deletions (size 5), sending progress updates, and calling node.remove() on each.async function deleteMultipleNodes(params) { const { nodeIds } = params || {}; const commandId = generateCommandId(); if (!nodeIds || !Array.isArray(nodeIds) || nodeIds.length === 0) { const errorMsg = "Missing or invalid nodeIds parameter"; sendProgressUpdate( commandId, "delete_multiple_nodes", "error", 0, 0, 0, errorMsg, { error: errorMsg } ); throw new Error(errorMsg); } console.log(`Starting deletion of ${nodeIds.length} nodes`); // Send started progress update sendProgressUpdate( commandId, "delete_multiple_nodes", "started", 0, nodeIds.length, 0, `Starting deletion of ${nodeIds.length} nodes`, { totalNodes: nodeIds.length } ); const results = []; let successCount = 0; let failureCount = 0; // Process nodes in chunks of 5 to avoid overwhelming Figma const CHUNK_SIZE = 5; const chunks = []; for (let i = 0; i < nodeIds.length; i += CHUNK_SIZE) { chunks.push(nodeIds.slice(i, i + CHUNK_SIZE)); } console.log(`Split ${nodeIds.length} deletions into ${chunks.length} chunks`); // Send chunking info update sendProgressUpdate( commandId, "delete_multiple_nodes", "in_progress", 5, nodeIds.length, 0, `Preparing to delete ${nodeIds.length} nodes using ${chunks.length} chunks`, { totalNodes: nodeIds.length, chunks: chunks.length, chunkSize: CHUNK_SIZE, } ); // Process each chunk sequentially for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) { const chunk = chunks[chunkIndex]; console.log( `Processing chunk ${chunkIndex + 1}/${chunks.length} with ${ chunk.length } nodes` ); // Send chunk processing start update sendProgressUpdate( commandId, "delete_multiple_nodes", "in_progress", Math.round(5 + (chunkIndex / chunks.length) * 90), nodeIds.length, successCount + failureCount, `Processing deletion chunk ${chunkIndex + 1}/${chunks.length}`, { currentChunk: chunkIndex + 1, totalChunks: chunks.length, successCount, failureCount, } ); // Process deletions within a chunk in parallel const chunkPromises = chunk.map(async (nodeId) => { try { const node = await figma.getNodeByIdAsync(nodeId); if (!node) { console.error(`Node not found: ${nodeId}`); return { success: false, nodeId: nodeId, error: `Node not found: ${nodeId}`, }; } // Save node info before deleting const nodeInfo = { id: node.id, name: node.name, type: node.type, }; // Delete the node node.remove(); console.log(`Successfully deleted node: ${nodeId}`); return { success: true, nodeId: nodeId, nodeInfo: nodeInfo, }; } catch (error) { console.error(`Error deleting node ${nodeId}: ${error.message}`); return { success: false, nodeId: nodeId, error: error.message, }; } }); // Wait for all deletions in this chunk to complete const chunkResults = await Promise.all(chunkPromises); // Process results for this chunk chunkResults.forEach((result) => { if (result.success) { successCount++; } else { failureCount++; } results.push(result); }); // Send chunk processing complete update sendProgressUpdate( commandId, "delete_multiple_nodes", "in_progress", Math.round(5 + ((chunkIndex + 1) / chunks.length) * 90), nodeIds.length, successCount + failureCount, `Completed chunk ${chunkIndex + 1}/${ chunks.length }. ${successCount} successful, ${failureCount} failed so far.`, { currentChunk: chunkIndex + 1, totalChunks: chunks.length, successCount, failureCount, chunkResults: chunkResults, } ); // Add a small delay between chunks if (chunkIndex < chunks.length - 1) { console.log("Pausing between chunks..."); await delay(1000); } } console.log( `Deletion complete: ${successCount} successful, ${failureCount} failed` ); // Send completed progress update sendProgressUpdate( commandId, "delete_multiple_nodes", "completed", 100, nodeIds.length, successCount + failureCount, `Node deletion complete: ${successCount} successful, ${failureCount} failed`, { totalNodes: nodeIds.length, nodesDeleted: successCount, nodesFailed: failureCount, completedInChunks: chunks.length, results: results, } ); return { success: successCount > 0, nodesDeleted: successCount, nodesFailed: failureCount, totalNodes: nodeIds.length, results: results, completedInChunks: chunks.length, commandId, }; }
- src/talk_to_figma_mcp/server.ts:798-828 (registration)MCP server registration of delete_multiple_nodes tool, including schema (nodeIds array) and proxy handler that forwards to Figma plugin via sendCommandToFigma.// Delete Multiple Nodes Tool server.tool( "delete_multiple_nodes", "Delete multiple nodes from Figma at once", { nodeIds: z.array(z.string()).describe("Array of node IDs to delete"), }, async ({ nodeIds }) => { try { const result = await sendCommandToFigma("delete_multiple_nodes", { nodeIds }); return { content: [ { type: "text", text: JSON.stringify(result) } ] }; } catch (error) { return { content: [ { type: "text", text: `Error deleting multiple nodes: ${error instanceof Error ? error.message : String(error) }`, }, ], }; } } );
- src/cursor_mcp_plugin/code.js:139-182 (handler)Switch case in Figma plugin's handleCommand that routes 'delete_multiple_nodes' command to the deleteMultipleNodes implementation.case "delete_multiple_nodes": return await deleteMultipleNodes(params); case "get_styles": return await getStyles(); case "get_local_components": return await getLocalComponents(); // case "get_team_components": // return await getTeamComponents(); case "create_component_instance": return await createComponentInstance(params); case "export_node_as_image": return await exportNodeAsImage(params); case "set_corner_radius": return await setCornerRadius(params); case "set_text_content": return await setTextContent(params); case "clone_node": return await cloneNode(params); case "scan_text_nodes": return await scanTextNodes(params); case "set_multiple_text_contents": return await setMultipleTextContents(params); case "get_annotations": return await getAnnotations(params); case "set_annotation": return await setAnnotation(params); case "scan_nodes_by_types": return await scanNodesByTypes(params); case "set_multiple_annotations": return await setMultipleAnnotations(params); case "set_layout_mode": return await setLayoutMode(params); case "set_padding": return await setPadding(params); case "set_axis_align": return await setAxisAlign(params); case "set_layout_sizing": return await setLayoutSizing(params); case "set_item_spacing": return await setItemSpacing(params); default: throw new Error(`Unknown command: ${command}`); } }
- Zod schema definition for delete_multiple_nodes input: array of node ID strings.{ nodeIds: z.array(z.string()).describe("Array of node IDs to delete"), },
- src/cursor_mcp_plugin/code.js:10-50 (helper)Helper function used by deleteMultipleNodes to send progress updates during chunked deletion process.function sendProgressUpdate( commandId, commandType, status, progress, totalItems, processedItems, message, payload = null ) { const update = { type: "command_progress", commandId, commandType, status, progress, totalItems, processedItems, message, timestamp: Date.now(), }; // Add optional chunk information if present if (payload) { if ( payload.currentChunk !== undefined && payload.totalChunks !== undefined ) { update.currentChunk = payload.currentChunk; update.totalChunks = payload.totalChunks; update.chunkSize = payload.chunkSize; } update.payload = payload; } // Send to UI figma.ui.postMessage(update); console.log(`Progress update: ${status} - ${progress}% - ${message}`); return update; }