Figma MCP local
A local, high-performance replacement for the hosted Figma MCP server that caches Figma files and exposes a local MCP endpoint for Cursor or any MCP client.
README
Design Intelligence Platform (Local MVP)
A local, high-performance replacement for the hosted Figma MCP server. It downloads Figma files once into a SQLite cache, builds a full-text search index over them, and exposes a local MCP endpoint that Cursor (or any MCP client) queries — without touching the Figma API.
Cursor ──► http://localhost:8787/mcp ──► SQLite cache ──► FTS5 search index
▲
│ only during explicit sync
Figma API
The cache is the source of truth. The Figma API is called in exactly three situations: validating
your token on connect, a cheap version check at the start of a sync, and the full file download
when the version changed (or --force).
Architecture
Clean architecture with constructor-based dependency injection; src/app.ts is the composition root that wires everything together.
src/
api/ REST routes (connect, sync, projects, status, logs, health)
mcp/ MCP server: 8 tools over Streamable HTTP (stateless)
figma/ Figma REST API client (axios, typed errors, request logging)
sync/ Parser: Figma document tree -> flattened node rows + search docs
database/ Drizzle schema, better-sqlite3 client (WAL), idempotent migrations
search/ FTS5 search repository (safe query building, bm25 ranking, snippets)
cache/ Cache metadata key/value store (file versions, bookkeeping)
config/ Zod-validated .env configuration
services/ AccountService, SyncService (job engine), QueryService, simplifier
repositories/ Row-level access: accounts, files/pages, nodes, components, styles, variables
types/ Figma API types + simplified domain types
utils/ Structured logger (JSON lines + ring buffer for the dashboard)
shared/ Typed application errors
frontend/ React + Vite + Tailwind dashboard (Connect / Projects / MCP Status)
tests/ Vitest suites incl. end-to-end MCP-over-HTTP tests with a mocked Figma API
scripts/ CLI sync
How data is stored
A Figma file is a single huge JSON tree. Instead of storing one blob (slow to query) or fully
normalizing every property (schema churn), each node becomes one row: queryable columns
(node_id, parent_id, page_id, type, name, depth, child_index) plus the node's own
JSON with children stripped. Subtrees are rebuilt breadth-first at query time down to a depth
limit. Search runs over an FTS5 virtual table indexing names and text content.
Simplified node format
get_node defaults to a compact design representation built for code generation: hex colors,
auto-layout expressed as flex terms (mode/gap/padding/justify/align), resolved typography, and
component instance names. Raw Figma JSON is available with format: "raw".
Installation
Requires Node.js 20+.
npm install
cp .env.example .env # optional; defaults work out of the box
npm run dev
- Dashboard (dev): http://localhost:5173 (proxies to the API)
- API + MCP server: http://localhost:8787
For a production-style run: npm run build && npm start — the built dashboard is then served
directly at http://localhost:8787.
Environment variables
| Variable | Default | Description |
|---|---|---|
PORT |
8787 |
REST + MCP server port |
DATABASE_URL |
sqlite.db |
SQLite database file path |
LOG_LEVEL |
info |
debug | info | warn | error |
FIGMA_MAX_RATE_LIMIT_RETRIES |
3 |
Automatic retries on a Figma 429 (0 disables) |
Using it
-
Connect — open the dashboard, paste a Figma personal access token (Figma → Settings → Security → Personal access tokens). When creating the token, grant these scopes:
current_user:read— used once to validate the tokenfile_content:read— required to download filesfile_metadata:read— recommended; lets re-syncs use the cheap Tier 3 metadata endpoint (the app falls back to a Tier 1 shallow fetch without it)file_variables:read— optional, Enterprise plans only
The token is validated against
/v1/meand stored in the local SQLite database. It is stored in plaintext — this is a single-user local dev tool; treatsqlite.dbaccordingly. -
Sync — paste a file key (the segment after
figma.com/design/in a file URL) and click Sync. The full file is downloaded, flattened into SQLite, and indexed. Re-syncs first do a cheap version check and no-op when nothing changed. -
Connect Cursor — add to your Cursor MCP settings:
{
"mcpServers": {
"design-intelligence": {
"type": "http",
"url": "http://localhost:8787/mcp"
}
}
}
Then ask Cursor things like "Generate the Login page", "Find all buttons", "List every page", "Find typography styles" — all answered from the local cache.
CLI sync
npm run sync -- <fileKey> # sync (version-checked)
npm run sync -- <fileKey> --force # re-download unconditionally
MCP tools
| Tool | Purpose |
|---|---|
sync_file |
Explicitly (re)download a file into the cache; chunked for huge files |
sync_node |
Incrementally re-sync one node/frame/page subtree (must already be cached) |
get_file_summary |
One-call overview: counts, page list, top components — orient before drilling in |
list_pages |
Pages of a cached file with their top-level frames |
get_node |
Node subtree — simplified (default) or raw; depth bounds the size |
search |
FTS over pages, frames, components, text and styles; limit/offset |
list_components |
Components / component sets with descriptions; limit/offset + total |
get_styles |
Shared styles and design variables; limit/offset + totals |
fileKey is optional on read tools when exactly one file is cached. Read tools are marked
readOnlyHint so clients like Cursor can auto-run them safely.
REST API
POST /api/connect · POST /api/sync · POST /api/sync-node · GET /api/projects ·
GET /api/status · GET /api/logs · GET /api/health · GET /api/connection
How sync works
GET /v1/files/:key/meta— compareversionagainst the cached one; stop if unchanged. This is a Tier 3 endpoint (large rate budget). Without thefile_metadata:readscope it falls back toGET /v1/files/:key?depth=1(Tier 1).GET /v1/files/:key— full download (no vector geometry). Tier 1 — the scarcest rate-limit class (per Figma's rate limits, roughly 10–20 requests/min on Dev/Full seats since Nov 2025), which is exactly why this platform caches instead of proxying.- Parse: flatten the document tree into node rows and search documents.
- Single SQLite transaction: replace file, pages, nodes, components, styles.
- Variables via
GET /v1/files/:key/variables/local— Enterprise-plan only; a 403 is expected on personal/pro plans and logged as a warning, not an error. - Rebuild the FTS5 index for the file.
Sync runs as a background job; poll GET /api/status or watch the dashboard. Nothing else ever
calls the Figma API.
For very large files, pass chunked: true (the sync_file tool / POST /api/sync) to download
page-by-page — a shallow ?depth=1 fetch for the page list, then one ?ids=<pageId> request per
page — instead of one giant whole-file response. It bounds peak payload/memory at the cost of more
Tier-1 requests (the 429 retry above absorbs transient limits).
Incremental sync
Iterating on one screen shouldn't re-download the whole file. sync_node (MCP) /
POST /api/sync-node fetches a single node via GET /v1/files/:key/nodes?ids=, re-roots the
returned subtree from the cached node's position, and atomically replaces just that branch — node
rows and their search index — while upserting any component/style metadata the response carries.
The node must already be cached from a prior full sync; a full sync_file remains the way to
reconcile structural changes such as added or deleted pages.
Scripts
npm run dev · npm run build · npm start · npm test · npm run lint · npm run format ·
npm run sync -- <fileKey>
Error handling
Typed errors with stable codes surface everywhere: INVALID_TOKEN, NOT_CONNECTED,
FILE_NOT_FOUND, CACHE_MISS, CACHE_EMPTY, RATE_LIMITED, SYNC_IN_PROGRESS,
VALIDATION_ERROR, FIGMA_API_ERROR. MCP tools return them as tool errors instead of crashing
the transport.
Future roadmap (designed for, not implemented)
Multiple accounts (the API client is already token-stateless), semantic/vector search (sits next to the FTS table), AI code generation (consumes the simplified node format), background sync, component dependency graphs, and Electron packaging.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。