| name | figma-context-mcp-cached |
| description | Cache-enabled Figma Context MCP server for AI agents to fetch and analyze Figma designs with persistent disk caching |
| triggers | ["fetch figma design data","get figma file contents","download figma images","analyze figma components","extract figma styles","cache figma file","refresh figma cache","prepare figma file for analysis"] |
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
export FIGMA_API_KEY="your-figma-api-key"
export FIGMA_CACHING='{"ttl":{"value":30,"unit":"d"},"cacheDir":"~/.cache/figma-mcp"}'
Configuration
Cache TTL Units
ms - milliseconds
s - seconds
m - minutes
h - hours
d - 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.
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/MyDesign?node-id=2777-9428",
"forceRefresh": false
}
}
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.
{
"name": "get_figma_data",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodeId": "2777-9428",
"depth": 5
}
}
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.
{
"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",
"pngScale": 2
}
}
Advanced image download with cropping:
{
"name": "download_figma_images",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodes": [
{
"nodeId": "2777-9428",
"fileName": "cropped-image.png",
"imageRef": "abc123def456",
"needsCropping": true,
"cropTransform": [[1, 0, 0], [0, 1, 0]],
"requiresImageDimensions": true
}
],
"pngScale": 3
}
}
Common Workflows
Workflow 1: Analyze a Figma Design
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/Dashboard?node-id=2777-9428"
}
}
{
"name": "get_figma_data",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K",
"nodeId": "2777-9428"
}
}
Workflow 2: Export Design Assets
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/Assets"
}
}
{
"name": "get_figma_data",
"arguments": {
"fileKey": "QlQwKAl9abcdhvlfvpM5K"
}
}
{
"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
{
"name": "figma_prepare_file",
"arguments": {
"figmaUrl": "https://www.figma.com/design/QlQwKAl9abcdhvlfvpM5K/Dashboard",
"forceRefresh": true
}
}
{
"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,
alignment: layoutAlign
};
}
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`;
css += ` width: ${layout.size.width}px;\n`;
css += ` height: ${layout.size.height}px;\n`;
if (colors[0]) {
css += ` background-color: ${colors[0]};\n`;
}
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:
rm -rf ~/.cache/figma-mcp/*
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_CACHING is set in config
- Ensure cache directory is writable
- Check TTL is reasonable (not 0 or negative)
{
"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-5678 or 1234:5678
- Use
forceRefresh: true to 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_file to check cache before fetching
- Avoid calling
get_figma_data with forceRefresh repeatedly
Stale Cache Data
Symptom: Design changes not reflected in results
Solution:
- Use
forceRefresh: true in figma_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:
chmod 755 ~/.cache/figma-mcp
{
"cacheDir": "~/my-figma-cache"
}
Best Practices
- Always call
figma_prepare_file first before get_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
forceRefresh when user explicitly requests latest data
- Don't specify
depth parameter unless user has specific need
- Parse globalVars for reusable design tokens (colors, fonts, spacing)
- Batch image downloads in single
download_figma_images call
- Use SVG for icons, PNG for photos/raster images
Integration Examples
Generate Tailwind Config from Figma
async function generateTailwindConfig(fileKey: string) {
await callTool('figma_prepare_file', {
figmaUrl: `https://www.figma.com/design/${fileKey}/DesignSystem`
});
const data = await callTool('get_figma_data', { fileKey });
const colors = {};
for (const [name, value] of Object.entries(data.globalVars.colors)) {
colors[name] = value;
}
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 });
const components = Object.entries(data.components).map(([id, comp]) => ({
id,
name: comp.name,
nodeId: id.replace(':', '-')
}));
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
});
}