Figma Context MCP Cached
Skill by ara.so — Design Skills collection.
Overview
Figma-Context-MCP-Cached is an MCP (Model Context Protocol) server that provides AI agents access to Figma design files with intelligent disk caching. It reduces API rate limits by caching Figma file data locally, making it ideal for AI coding agents that need to frequently access design specifications.
Key Features:
- Persistent disk caching with configurable TTL
- Smart file preparation with node validation
- Force refresh capability for latest design data
- Image download support (SVG/PNG)
- Automatic system downloads folder detection
- Three core MCP tools:
figma_prepare_file,get_figma_data,download_figma_images
Installation
For MCP Clients (Claude Desktop, Cursor, etc.)
Add to your MCP settings configuration:
{
"mcpServers": {
"figma-context-mcp-cached": {
"command": "npx",
"args": [
"-y",
"@pactortester/figma-mcp-cached",
"--stdio",
"--figma-api-key=${FIGMA_API_KEY}",
"--figma-caching={\"ttl\":{\"value\":30,\"unit\":\"d\"},\"cacheDir\":\"~/.cache/figma-mcp\"}"
]
}
}
}
Environment Variables
# Required
export FIGMA_API_KEY="your-figma-api-key"
# Optional - if not using command-line args
export FIGMA_CACHING='{"ttl":{"value":30,"unit":"d"},"cacheDir":"~/.cache/figma-mcp"}'
Configuration
Cache TTL Units
ms- millisecondss- secondsm- minutesh- hoursd- days
Cache Directory
Default locations by platform:
- Linux:
~/.cache/figma-mcp - macOS:
~/Library/Caches/FigmaMcp - Windows:
%LOCALAPPDATA%/FigmaMcpCache
Custom directory (relative or absolute):
{
"cacheDir": "~/my-custom-cache"
}
MCP Tools Usage
1. figma_prepare_file - Prepare Figma File
Always call this first before fetching Figma data. It checks cache validity and optionally forces refresh.
// Tool call structure
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/MyDesign?node-id=2777-9428",
"forceRefresh": false // Set to true to get latest data
}
}
When to use forceRefresh: true:
- User says "get the latest design"
- User mentions design was just updated
- User says "refresh the figma file"
- Cache is stale but not yet expired
Response indicates:
- Cache hit (file ready to use)
- Cache miss (file downloaded and cached)
- Node validation result (if nodeId in URL)
- Whether file was refreshed
2. get_figma_data - Fetch Design Data
Retrieves the actual Figma file structure, styles, and component data.
// Tool call structure
{
"name": "get_figma_data",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodeId": "2777-9428", // Optional: specific node to fetch
"depth": 5 // Optional: tree traversal depth (omit unless user requests)
}
}
Extracting fileKey and nodeId from URL:
https://www.figma.com/design/{fileKey}/Title?node-id={nodeId}
Example: https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/MyDesign?node-id=2777-9428
fileKey = "QlQwKAl9abcdhvlfvpM5K"
nodeId = "2777-9428"
Response structure:
{
"metadata": {
"name": "Design System",
"lastModified": "2026-05-15T10:32:24Z"
},
"nodes": [
{
"id": "2777:9428",
"name": "Hero Section",
"type": "FRAME",
"children": [...],
"absoluteBoundingBox": {
"x": 0,
"y": 0,
"width": 1440,
"height": 800
},
"fills": [...],
"strokes": [...]
}
],
"globalVars": {
"colors": {...},
"typography": {...}
},
"components": {...},
"componentSets": {...}
}
3. download_figma_images - Export Images
Downloads PNG or SVG assets from Figma nodes.
// Tool call structure
{
"name": "download_figma_images",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodes": [
{
"nodeId": "2777-9428",
"fileName": "hero-image.png"
},
{
"nodeId": "2777-9430",
"fileName": "icon-star.svg"
}
],
"localPath": "/absolute/path/to/save", // Optional: defaults to system Downloads
"pngScale": 2 // Optional: 1x, 2x, 3x for PNG export
}
}
Advanced image download with cropping:
{
"name": "download_figma_images",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodes": [
{
"nodeId": "2777-9428",
"fileName": "cropped-image.png",
"imageRef": "abc123def456", // Required for image fills
"needsCropping": true,
"cropTransform": [[1, 0, 0], [0, 1, 0]], // Figma transform matrix
"requiresImageDimensions": true // Returns width/height for CSS
}
],
"pngScale": 3
}
}
Common Workflows
Workflow 1: Analyze a Figma Design
// Step 1: Prepare the file (checks cache, validates nodes)
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/Dashboard?node-id=2777-9428"
}
}
// Step 2: Fetch the design data
{
"name": "get_figma_data",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodeId": "2777-9428"
}
}
// Step 3: Analyze the response
// - Extract layout structure from nodes
// - Get color palette from globalVars.colors
// - Identify reusable components
// - Generate CSS/Tailwind from styles
Workflow 2: Export Design Assets
// Step 1: Prepare file
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/Assets"
}
}
// Step 2: Get file data to identify exportable nodes
{
"name": "get_figma_data",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K"
}
}
// Step 3: Download images
{
"name": "download_figma_images",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodes": [
{"nodeId": "123-456", "fileName": "logo.svg"},
{"nodeId": "789-012", "fileName": "hero@2x.png"}
],
"pngScale": 2
}
}
Workflow 3: Force Refresh After Design Update
// When user says "the design just changed, get the latest"
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/Dashboard",
"forceRefresh": true // Bypasses cache, fetches fresh data
}
}
// Then fetch data normally
{
"name": "get_figma_data",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K"
}
}
Parsing Figma Node Data
Extract Layout Information
function extractLayout(node: any) {
const { absoluteBoundingBox, layoutMode, layoutAlign } = node;
return {
position: {
x: absoluteBoundingBox.x,
y: absoluteBoundingBox.y
},
size: {
width: absoluteBoundingBox.width,
height: absoluteBoundingBox.height
},
layout: layoutMode, // 'HORIZONTAL', 'VERTICAL', 'NONE'
alignment: layoutAlign // 'MIN', 'CENTER', 'MAX', 'STRETCH'
};
}
Extract Color Styles
function extractColors(node: any) {
const fills = node.fills || [];
return fills
.filter(fill => fill.type === 'SOLID')
.map(fill => {
const { r, g, b, a } = fill.color;
return `rgba(${Math.round(r*255)}, ${Math.round(g*255)}, ${Math.round(b*255)}, ${a})`;
});
}
Extract Typography
function extractTypography(node: any) {
if (node.type !== 'TEXT') return null;
const { style } = node;
return {
fontFamily: style.fontFamily,
fontSize: style.fontSize,
fontWeight: style.fontWeight,
lineHeight: style.lineHeightPx || style.lineHeightPercentFontSize,
letterSpacing: style.letterSpacing,
textAlign: style.textAlignHorizontal
};
}
Generate CSS from Figma Node
function generateCSS(node: any): string {
const layout = extractLayout(node);
const colors = extractColors(node);
const typography = node.type === 'TEXT' ? extractTypography(node) : null;
let css = `.${node.name.toLowerCase().replace(/\s+/g, '-')} {\n`;
// Layout
css += ` width: ${layout.size.width}px;\n`;
css += ` height: ${layout.size.height}px;\n`;
// Colors
if (colors[0]) {
css += ` background-color: ${colors[0]};\n`;
}
// Typography
if (typography) {
css += ` font-family: '${typography.fontFamily}';\n`;
css += ` font-size: ${typography.fontSize}px;\n`;
css += ` font-weight: ${typography.fontWeight};\n`;
}
css += `}\n`;
return css;
}
Cache Management
Check Cache Status
The cache is transparent, but you can infer status from figma_prepare_file response:
"File is already cached and valid"→ Cache hit"Successfully cached file"→ Cache miss, file downloaded"Cache refreshed"→ Force refresh executed
Manual Cache Clearing
Cache files are stored as JSON in the configured directory:
# Linux/macOS
rm -rf ~/.cache/figma-mcp/*
# Windows (PowerShell)
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\FigmaMcpCache\*"
Cache Naming Convention
Files are cached as: {fileKey}.json
Example: QlQwKAl9abcdhvlfvpM5K.json
Troubleshooting
Cache Not Working
Symptom: Every request hits Figma API
Check:
- Verify
FIGMA_CACHINGis set in config - Ensure cache directory is writable
- Check TTL is reasonable (not 0 or negative)
// Valid caching config
{
"ttl": {"value": 30, "unit": "d"},
"cacheDir": "~/.cache/figma-mcp"
}
Node Not Found Error
Symptom: figma_prepare_file reports node doesn't exist
Solution:
- Verify nodeId format:
1234-5678or1234:5678 - Use
forceRefresh: trueto update cache - Check if node was deleted in Figma
Rate Limit Errors
Symptom: 429 Too Many Requests from Figma API
Solution:
- Increase cache TTL (e.g., from 1 day to 30 days)
- Use
figma_prepare_fileto check cache before fetching - Avoid calling
get_figma_datawithforceRefreshrepeatedly
Stale Cache Data
Symptom: Design changes not reflected in results
Solution:
- Use
forceRefresh: trueinfigma_prepare_file - Reduce cache TTL for frequently updated files
- Clear cache manually during active design iterations
Permission Errors
Symptom: Cannot write to cache directory
Solution:
# Linux/macOS
chmod 755 ~/.cache/figma-mcp
# Or set custom directory in user space
{
"cacheDir": "~/my-figma-cache"
}
Best Practices
- Always call
figma_prepare_filefirst beforeget_figma_data - Use longer cache TTL (7-30 days) for stable design systems
- Use shorter cache TTL (1-6 hours) for active design work
- Use
forceRefreshwhen user explicitly requests latest data - Don't specify
depthparameter unless user has specific need - Parse globalVars for reusable design tokens (colors, fonts, spacing)
- Batch image downloads in single
download_figma_imagescall - Use SVG for icons, PNG for photos/raster images
Integration Examples
Generate Tailwind Config from Figma
async function generateTailwindConfig(fileKey: string) {
// Prepare and fetch file
await callTool('figma_prepare_file', {
figmaUrl: `https://www.figma.com/design/${fileKey}/DesignSystem`
});
const data = await callTool('get_figma_data', { fileKey });
// Extract colors from globalVars
const colors = {};
for (const [name, value] of Object.entries(data.globalVars.colors)) {
colors[name] = value; // Already in hex/rgba format
}
// Generate Tailwind config
return {
theme: {
extend: {
colors,
fontFamily: data.globalVars.typography || {}
}
}
};
}
Export Component Library
async function exportComponents(fileKey: string, outputDir: string) {
const data = await callTool('get_figma_data', { fileKey });
// Find all component instances
const components = Object.entries(data.components).map(([id, comp]) => ({
id,
name: comp.name,
nodeId: id.replace(':', '-')
}));
// Download each component as SVG
const nodes = components.map(c => ({
nodeId: c.nodeId,
fileName: `${c.name.toLowerCase().replace(/\s+/g, '-')}.svg`
}));
await callTool('download_figma_images', {
fileKey,
nodes,
localPath: outputDir
});
}