Skip to main content
Glama
by alucardeht
figma.js2.67 kB
import axios from "axios"; import RateLimiter from "../classes/RateLimiter.js"; const FIGMA_API_BASE = "https://api.figma.com/v1"; const TIER_LIMITS = { 1: { requests: 10, window: 60000 }, 2: { requests: 25, window: 60000 }, 3: { requests: 50, window: 60000 }, }; class FigmaClient { constructor(token) { this.token = token; this.rateLimiter = new RateLimiter(TIER_LIMITS); this.cache = new Map(); } async request(endpoint, params = {}, tier = 1) { await this.rateLimiter.waitForSlot(tier); const cacheKey = `${endpoint}:${JSON.stringify(params)}`; if (this.cache.has(cacheKey)) { return this.cache.get(cacheKey); } try { const response = await axios.get(`${FIGMA_API_BASE}${endpoint}`, { params, headers: { "X-Figma-Token": this.token }, }); this.cache.set(cacheKey, response.data); return response.data; } catch (error) { if (error.response?.status === 429) { const retryAfter = parseInt(error.response.headers["retry-after"] || "60", 10); await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000)); return this.request(endpoint, params, tier); } throw error; } } async getFile(fileKey, depth = 1) { return await this.request(`/files/${fileKey}`, { depth }, 1); } async getNode(fileKey, nodeId) { const data = await this.request(`/files/${fileKey}/nodes`, { ids: nodeId }, 1); return data.nodes[nodeId]?.document; } async getImage(fileKey, nodeIds, format = "png", scale = 2) { const ids = Array.isArray(nodeIds) ? nodeIds.join(",") : nodeIds; return await this.request(`/images/${fileKey}`, { ids, format, scale }, 1); } async getStyles(fileKey) { return await this.request(`/files/${fileKey}/styles`, {}, 2); } findPageByName(file, pageName) { const lowerName = pageName.toLowerCase(); return file.document.children.find((p) => p.name.toLowerCase().includes(lowerName)); } findFrameByName(page, frameName) { const lowerName = frameName.toLowerCase(); const findInChildren = (children) => { for (const child of children) { if ( (child.type === "FRAME" || child.type === "COMPONENT" || child.type === "COMPONENT_SET") && child.name.toLowerCase().includes(lowerName) ) { return child; } if (child.children) { const found = findInChildren(child.children); if (found) return found; } } return null; }; return findInChildren(page.children || []); } clearCache() { this.cache.clear(); } } export default FigmaClient;

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

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