Skip to main content
Glama
aihustlerahul-ui

Figma MCP local

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

Related MCP server: YetAnotherFigmaMCP

Installation

Requires Node.js 20+.

npm install
cp .env.example .env   # optional; defaults work out of the box
npm run dev

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/localEnterprise-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.

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aihustlerahul-ui/Figma-mcp-local'

If you have feedback or need assistance with the MCP directory API, please join our Discord server