Skip to main content
Glama

analyze_figma_file

Extract and analyze Figma file structures to identify node hierarchies and relationships. Input a Figma URL and optional depth to retrieve organized data for design insights.

Instructions

Analyze a Figma file structure to understand its nodes and hierarchy

Input Schema

NameRequiredDescriptionDefault
depthNoOptional depth parameter to limit the node tree depth
figmaUrlYesThe URL of the Figma file to analyze

Input Schema (JSON Schema)

{ "properties": { "depth": { "description": "Optional depth parameter to limit the node tree depth", "type": "number" }, "figmaUrl": { "description": "The URL of the Figma file to analyze", "type": "string" } }, "required": [ "figmaUrl" ], "type": "object" }

Implementation Reference

  • The main handler function that orchestrates the analysis: extracts Figma IDs, generates the node tree using FigmaTreeGenerator, formats the result or error as CallToolResult.
    async function doAnalyzeFigmaFile(figmaUrl: string, depth?: number): Promise<CallToolResult> { try { // Get Figma API Key const figmaApiKey = process.env.FIGMA_API_KEY; if (!figmaApiKey) { throw new Error('FIGMA_API_KEY not configured'); } // Extract file ID and node ID from URL const { fileId, nodeId } = extractFigmaIds(figmaUrl); if (!fileId) { throw new Error('Could not extract file ID from URL'); } if (!nodeId) { throw new Error('No node ID specified in URL'); } // Generate the node tree const treeGenerator = new FigmaTreeGenerator(figmaApiKey); const tree = await treeGenerator.generateNodeTree(fileId, nodeId, depth); // Return the result return { content: [ { type: 'text', text: `Successfully analyzed Figma file: ${figmaUrl}`, }, { type: 'text', text: `File ID: ${fileId}`, }, { type: 'text', text: `Node ID: ${nodeId}`, }, { type: 'text', text: 'Node Tree Structure:', }, { type: 'text', text: JSON.stringify(tree, null, 2), }, ], }; } catch (error) { console.error('Error analyzing Figma file:', error); // Return error as text content instead of throwing return { content: [ { type: 'text', text: `Error analyzing Figma file: ${error instanceof Error ? error.message : 'Unknown error'}` } ] }; } }
  • Tool definition including name, description, and input schema for validation.
    const ANALYZE_FIGMA_FILE: Tool = { name: 'analyze_figma_file', description: 'Analyze a Figma file structure to understand its nodes and hierarchy', inputSchema: { type: 'object', properties: { figmaUrl: { type: 'string', description: 'The URL of the Figma file to analyze', }, depth: { type: 'number', description: 'Optional depth parameter to limit the node tree depth', }, }, required: ['figmaUrl'], }, };
  • src/index.ts:69-71 (registration)
    Registers the tool in the ListToolsRequestSchema handler.
    server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ANALYZE_FIGMA_FILE], }));
  • src/index.ts:75-78 (registration)
    Dispatches tool calls to the handler in CallToolRequestSchema.
    if (request.params.name === 'analyze_figma_file') { const input = request.params.arguments as { figmaUrl: string; depth?: number }; return doAnalyzeFigmaFile(input.figmaUrl, input.depth); }
  • Core helper class for generating and processing the Figma node tree via API, used by the main handler.
    export class FigmaTreeGenerator { private readonly apiKey: string; private readonly baseUrl = 'https://api.figma.com/v1'; constructor(apiKey: string) { this.apiKey = apiKey; } async generateNodeTree(fileId: string, nodeId: string, depth?: number): Promise<FigmaNode> { try { // Construct URL with optional depth parameter let url = `${this.baseUrl}/files/${fileId}/nodes?ids=${nodeId}`; if (depth !== undefined) { url += `&depth=${depth}`; } // Make request to Figma API const response = await axios.get<FigmaNodesResponse>( url, { headers: { 'X-Figma-Token': this.apiKey } } ); // Check if the node exists in the response if (!response.data.nodes[nodeId]) { throw new Error(`Node ${nodeId} not found in file ${fileId}`); } // Extract the document from the response const nodeData = response.data.nodes[nodeId].document; // Process the node tree return this.processNode(nodeData); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to fetch Figma node tree: ${errorMessage}`); } } private processNode(node: FigmaNode): FigmaNode { // Create a new node object to avoid mutating the original const processedNode: FigmaNode = { id: node.id, name: node.name, type: node.type }; // If this is an INSTANCE node, we stop traversal here // By not adding children property, we indicate this is a terminal node if (node.type === 'INSTANCE') { return processedNode; } // If node has children, process them recursively if (node.children && node.children.length > 0) { processedNode.children = node.children.map(child => this.processNode(child)); } else { processedNode.children = []; } return processedNode; } }
  • Utility function to parse Figma file and node IDs from the input URL.
    export function extractFigmaIds(figmaUrl: string): { fileId: string, nodeId: string | null } { try { const url = new URL(figmaUrl); // Extract the file ID from the URL path const pathParts = url.pathname.split('/'); let fileIdIndex = -1; // Look for file/design/proto in the URL path for (let i = 0; i < pathParts.length; i++) { if (pathParts[i] === 'file' || pathParts[i] === 'design' || pathParts[i] === 'proto') { fileIdIndex = i + 1; break; } } if (fileIdIndex === -1 || fileIdIndex >= pathParts.length) { throw new Error('Invalid Figma URL format: missing file/design/proto segment'); } const fileId = pathParts[fileIdIndex]; // Extract node ID from query parameters if present const nodeId = url.searchParams.get('node-id') || null; return { fileId, nodeId }; } catch (error) { throw new Error('Invalid Figma URL format'); } }

Other Tools

Related Tools

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/moonray/mcp-figma'

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