Figma MCP local

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.

Category
Visit Server

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

  1. 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 token
    • file_content:read — required to download files
    • file_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/me and stored in the local SQLite database. It is stored in plaintext — this is a single-user local dev tool; treat sqlite.db accordingly.

  2. 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.

  3. 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

  1. GET /v1/files/:key/meta — compare version against the cached one; stop if unchanged. This is a Tier 3 endpoint (large rate budget). Without the file_metadata:read scope it falls back to GET /v1/files/:key?depth=1 (Tier 1).
  2. 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.
  3. Parse: flatten the document tree into node rows and search documents.
  4. Single SQLite transaction: replace file, pages, nodes, components, styles.
  5. 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.
  6. 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.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured