@alucardeht/figma-mcp
MCP server for Figma API with intelligent context management and token optimization.
v3.0.0 — Compact tree output format with 95% token savings.
Installation
Claude Code
claude mcp add figma -e FIGMA_ACCESS_TOKEN=your-token-here -- npx -y github:alucardeht/figma-mcp
Get your Figma Token
- Open Figma Settings
- Navigate to Personal access tokens
- Click Create a new token
- Copy the token immediately (it won't be shown again)
Requirements
Figma Plan
The Figma REST API works with any plan, but rate limits differ significantly:
| Plan | File Access | Rate Limit |
|---|---|---|
| Starter (Free) | 6 requests/month | Impractical for real use |
| Professional | Unlimited | 120 req/min |
| Organization | Unlimited | 480 req/min |
Important: Free accounts are limited to 6 API calls per month for file content. This makes the MCP server impractical without a paid plan.
Dev Mode is not required — this MCP uses the REST API, not Dev Mode features.
Features
Compact Tree Output (NEW in v3.0)
- 95% token reduction: 205k chars → 10k chars for typical landing pages
- ASCII tree format: Clear hierarchical structure with
├─,└─,│ - Essential info preserved: Positions, dimensions, colors, layouts, overflow indicators
Example output:
Landing page [1440x2462 bg:#f2f2f2]
├─ header [1440x469]
│ ├─ nav [1440x81 row gap:99]
│ │ ├─ logo [155x30 INSTANCE]
│ │ └─ navHeaderLinks [456x49 row gap:8]
│ └─ zipCode [1188x147 bg:#fff radius:20]
├─ aboutContainer [1169x122 row]
│ ├─ aboutBox [391x122 radius:25]
│ └─ aboutBox [408x122 radius:25]
└─ footer [1440x90 row gap:309]
Smart Navigation
- Name-based access: Use human-readable names, no IDs required
- Partial matching: "Landing" matches "Landing page"
- Session state: Maintains context across requests
Invisible Element Filtering
By default, elements with visible: false in Figma are excluded from all MCP outputs:
- Frame structure (
get_frame_info) - Only visible elements in the tree - Asset extraction (
extract_assets) - Only visible icons and images - Style collection (
extract_styles) - Only styles from visible elements - Page analysis (
analyze_page_structure) - Only visible sections and components
This ensures the MCP output matches what you actually see in Figma's design view, not hidden elements used for design iteration, disabled variants, or placeholder components.
Why this matters: Designers often hide elements (placeholders, alternative versions, work in progress). Without filtering, the AI model would see and potentially implement these invisible elements, causing divergence from the intended design.
Asset Management
- Organized extraction: Assets saved to
icons/andimages/folders - Design tokens: Extract colors, typography, effects
- Configurable screenshots: Scale 1-4x with dimension limits
Available Tools
Navigation
| Tool | Description |
|---|---|
list_pages(file_key) | List all pages in a file |
list_frames(file_key, page_name) | List frames on a page |
get_frame_info(file_key, page_name, frame_name, depth?) | Get frame structure in compact format |
get_frame_info(file_key, node_id?, depth?) | Get frame via node_id (faster direct access) |
search_components(file_key, query) | Find components by name |
Extraction
| Tool | Description |
|---|---|
get_screenshot(file_key, page_name, frame_name) | Export frame as PNG |
get_screenshot(file_key, node_id?) | Export frame via node_id (faster direct access) |
extract_styles(file_key, page_name, frame_name) | Extract design tokens |
extract_assets(file_key, page_name, frame_name) | Export SVGs and images |
get_file_styles(file_key) | List published styles |
Validation
| Tool | Description |
|---|---|
validate_implementation(file_key, url, figma_node_id, ...) | Pixel-perfect comparison between Figma and browser, results organized by visual sections with match scores, bounds, colors, and CSS tree |
check_layout_bounds(file_key, page_name, frame_name) | Detect content overflow |
compare_element_position(file_key, page_name, frame_name, element_name, browser_x, browser_y) | Compare position: Figma vs browser |
compare_element_dimensions(file_key, page_name, frame_name, element_name, browser_width, browser_height) | Compare dimensions: Figma vs browser |
compare_visual(file_key, page_name, frame_name, screenshot_path) | Pixel-perfect diff with pixelmatch |
verify_elements_present(file_key, page_name, frame_name, element_names) | Check elements exist in DOM |
verify_assets_loaded(file_key, page_name, frame_name) | Verify images are loaded |
validate_responsive_breakpoint(file_key, page_name, frame_name, viewport_width) | Validate specific viewport |
test_all_breakpoints(file_key, page_name, frame_name) | Test mobile, tablet, desktop |
Session
| Tool | Description |
|---|---|
repeat_last() | Replay previous response from cache |
get_session_state() | View current session state |
reset_session() | Clear all cached data |
Direct Access via Node ID
Both get_frame_info and get_screenshot accept node_id as an alternative to page_name + frame_name for faster, direct access.
How to get node_id:
- Open frame in Figma editor
- Copy the ID from the URL:
https://www.figma.com/design/FILE_KEY/...?node-id=NODE_ID - Node ID format example:
40000056-28165
Usage:
get_frame_info(file_key="h75vgHNcwxfHkRBbI53RRu", node_id="40000056-28165", depth=4)
get_screenshot(file_key="h75vgHNcwxfHkRBbI53RRu", node_id="40000056-28165")
Benefits:
- Skips page/frame name lookup (1 fewer API call)
- More direct and reliable
- Useful for specific design reviews
Compact Format Reference
The get_frame_info tool returns a compact tree format optimized for LLM context:
element-name [[x,y wxh] attributes]
├─ child [[x,y wxh] attributes]
│ └─ grandchild [wxh attributes]
└─ sibling [wxh attributes]
Attributes shown:
bg:#hex— Background colorrow/col— Layout directiongap:N— Spacing between childrenradius:N— Border radiusshadow— Has drop shadowINSTANCE/VECTOR/TEXT— Node type↓overflow:Npx— Content overflows bounds
Example Workflow
1. list_pages("h75vgHNcwxfHkRBbI53RRu")
→ ["Home", "Components", "-> Validado"]
2. list_frames(file_key, "Validado")
→ ["Landing page", "Login", "Dashboard"]
3. get_frame_info(file_key, "Validado", "Landing page", depth=4)
→ Compact tree with full structure (165 lines, ~2.5k tokens)
4. extract_assets(file_key, "Validado", "Landing page")
→ icons/icon-1.svg, icons/icon-2.svg, images/hero.png
Rate Limits
| Plan | Requests/min |
|---|---|
| Free | 120 |
| Professional | 240 |
| Organization | 480 |
Use pagination with continue=true to stay within limits.
License
MIT
Issues? Open an issue
