Skip to main content
Glama
KaiUweHella

figma-bridge-mcp

by KaiUweHella

figma-bridge-mcp

Un servidor MCP local que permite a los asistentes de IA inspeccionar, crear y actualizar diseños en Figma Desktop. Se conecta a través de un pequeño plugin de desarrollo de Figma y expone herramientas enfocadas para capturas de pantalla, especificaciones de diseño, renderizado JSX, tokens, activos, componentes, FigJam y Figma Slides.

Todo se ejecuta en 127.0.0.1. No se requiere un token de acceso personal de Figma. Sin nube. Sin parcheo binario de la aplicación Figma.

Un complemento REST opcional añade historial de versiones, comentarios y metadatos de bibliotecas publicadas. Su token de Figma permanece en su máquina y nunca se coloca en la configuración de su cliente MCP ni en el chat.

Requisitos: Node.js 18 o superior, Figma Desktop y un cliente MCP que pueda iniciar servidores stdio locales.

Codex, Claude Code y Cursor: MCP y habilidades en un solo paquete

Figma Bridge incluye tres habilidades compartidas enfocadas más adaptadores de plugin ligeros para los tres clientes:

  • figma-bridge-design-to-code — implementación exacta de Figma en la pila objetivo;

  • figma-bridge-code-to-figma — pantallas semánticas y componentizadas desde el código;

  • figma-bridge-component-library — tokens, estilos, componentes, variantes y propiedades.

Cliente

Formato del plugin

Ruta de instalación completa

Codex / ChatGPT

.codex-plugin/plugin.json

Mercado de Codex de este repositorio

Claude Code

.claude-plugin/plugin.json

Mercado de Claude de este repositorio

Cursor

Agent Plugins 1.0 (plugin.json)

Mercado de equipo respaldado por GitHub o clon local

Los adaptadores descubren todos el mismo directorio skills/ e inician el mismo paquete MCP local. Los usuarios no descargan ni mantienen las habilidades por separado.

Para Codex, añada este repositorio como mercado e instale el paquete:

codex plugin marketplace add KaiUweHella/figma-bridge-mcp
codex plugin add figma-bridge-mcp@figma-bridge

Este es un mercado de repositorios alojado en GitHub, no un envío al directorio universal de plugins de OpenAI. El catálogo sigue al repositorio, mientras que cada entrada de plugin publicada fija una etiqueta Git exacta v<version> e inicia la versión de tiempo de ejecución npm correspondiente. Por lo tanto, main y @latest no pueden mover silenciosamente un paquete de habilidades instalado a un contrato de servidor diferente.

Para Claude Code, añada este repositorio como mercado e instale el paquete:

claude plugin marketplace add KaiUweHella/figma-bridge-mcp
claude plugin install figma-bridge-mcp@figma-bridge

El mercado de Claude utiliza la misma versión fijada de GitHub y el árbol de habilidades compartido. El paquete npm correspondiente debe publicarse antes de que los usuarios instalen esa versión, porque el plugin inicia su servidor stdio local a través de npx.

Para Cursor Teams o Enterprise, importe este repositorio de GitHub en un mercado de equipo e instale Figma Bridge desde Customize. Los usuarios individuales y contribuidores pueden usar la misma fuente de GitHub sin una lista central de Cursor: clone la versión etiquetada, enlace ese clon en Cursor y recargue la ventana:

mkdir -p ~/.cursor/plugins/local
ln -s /absolute/path/to/figma-bridge-mcp ~/.cursor/plugins/local/figma-bridge-mcp

Cursor detecta el manifiesto raíz de Agent Plugin y carga tanto la habilidad como el servidor MCP.

Los clientes sin soporte de plugin o Agent Skill siguen usando la configuración de servidor normal a continuación. Aún reciben el flujo de trabajo obligatorio compacto a través de las instrucciones MCP, los comandos invocados por el usuario design-to-code, code-to-figma y create-figma-component.

Inicio rápido

1. Añadir el servidor MCP (alternativa solo MCP)

Use esto cuando la instalación completa del plugin no esté disponible o solo quiera las herramientas MCP sin la habilidad incluida. La configuración con npx no necesita clonación ni paso de compilación. Para Claude Code:

claude mcp add figma-bridge -- npx -y figma-bridge-mcp@latest

Para otro cliente MCP, añada la configuración de servidor equivalente:

{
  "mcpServers": {
    "figma-bridge": {
      "command": "npx",
      "args": ["-y", "figma-bridge-mcp@latest"]
    }
  }
}

Reinicie el cliente MCP si no descubre el servidor inmediatamente. No hay intencionalmente un bloque env: el puente crea sus credenciales locales durante el emparejamiento.

git clone https://github.com/KaiUweHella/figma-bridge-mcp.git
cd figma-bridge-mcp
npm install
{
  "mcpServers": {
    "figma-bridge": {
      "command": "node",
      "args": ["/absolute/path/to/figma-bridge-mcp/src/server.js"]
    }
  }
}

2. Emparejar Figma Desktop una vez

  1. Pida a su asistente de IA que se conecte a Figma, o llame a figma_connect directamente. Inicia el puente local y devuelve una clave de acceso más una ruta de manifiesto del plugin.

  2. En Figma Desktop: Plugins → Development → Import plugin from manifest… y elija ~/.figma-bridge-mcp/plugin/manifest.json (la ruta devuelta por figma_connect).

  3. Abra Plugins → Development → Figma Bridge, pegue la clave de acceso y haga clic en Save & connect.

  4. Cuando el plugin muestre Connected (authenticated), el asistente puede trabajar con ese archivo de Figma. El emparejamiento se recuerda; en sesiones posteriores, solo vuelva a abrir el plugin en el archivo que desee usar.

Figma Dev Mode necesita adaptadores separados porque Figma no admite combinar el objetivo del editor FigJam existente con dev en un solo manifiesto:

  • Importe ~/.figma-bridge-mcp/plugin/manifest.dev.json para Figma Bridge Dev Mode. Mantiene el puente MCP autenticado conectado para selección, inspección, especificaciones y exportaciones. Dev Mode es de solo lectura, por lo que el renderizado y las ediciones del lienzo aún requieren cambiar el archivo al modo Design y abrir el plugin normal Figma Bridge allí.

3. Usarlo con Figma

Seleccione un marco o capa en Figma y describa el resultado que desea. Por ejemplo:

  • "Inspecciona mi selección actual y explica su diseño."

  • "Crea una tarjeta de configuración junto al marco seleccionado."

  • "Exporta los tokens y activos de la pantalla seleccionada a este proyecto."

  • "Implementa el marco seleccionado y luego compara el resultado con Figma."

El asistente puede leer la selección actual, capturar capturas de pantalla y especificaciones, renderizar JSX, exportar activos o aplicar ediciones específicas. Mantenga el plugin Figma Bridge abierto en cada documento al que el asistente deba acceder. Si hay más de un documento conectado, pase una URL de Figma o clave de archivo para que el objetivo sea inequívoco.

Related MCP server: tellfigma

Cómo funciona

MCP client ──stdio──▶ figma-bridge-mcp (src/)
                        │
                    MCP tool adapters ─▶ Capability Catalog ─▶ CommandPlan
                                                                  │
                                          ┌───────────────────────┴──────────┐
                                  Command Application Modules   generic CLI adapter
                                             │            │
                                      Design Capture      │
                                      Asset Policy        │
                                             └──────┬─────┘
                                      Daemon Client Module
                                             │  HTTP: signed requests
                                             ▼
                                  local daemon :3456–3460
                                             │  WS: challenge/response
                                             ▼
                                  Figma Bridge plugin in Figma Desktop
  • El motor se encuentra en engine/. Comenzó como un fork de figma-ds-cli v2.1.0 y ha divergido mucho más allá (ver atribución). El "modo Yolo" de Chrome-DevTools — que parchea el binario de la aplicación Figma — se eliminó por completo; no hay ninguna ruta de código hacia él.

  • Las lecturas MCP especializadas (figma_spec, figma_inspect, figma_screenshot) se ejecutan directamente a través de Módulos de Aplicación de Comandos que devuelven valores. MCP y CLI son adaptadores ligeros sobre las mismas implementaciones; el genérico figma_run sigue siendo el adaptador CLI de procesos hijo deliberadamente amplio. Un Módulo de Cliente Daemon gestiona la firma, los tiempos de espera y los errores de transporte para ambas rutas.

  • El Módulo de Captura de Diseño recorre un nodo explícito una vez y proyecta localmente la estructura, el estilo y los formatos de salida sin pérdida a partir de esos mismos hechos. Una Captura se reutiliza solo después de que una sonda de revisión económica demuestre que la conexión del plugin autenticado y la revisión del documento de Figma no han cambiado. La falta o inestabilidad de los metadatos de revisión deshabilita la reutilización; las llamadas de selección y sección nombrada permanecen sin caché en este primer Slice. Las Capturas distinguen entre Auto Layout/Grid de Figma creado por el autor, la heurística inferredAutoLayout marcada por Figma y el fallback geométrico. También preservan los metadatos semánticos/fallback de Código a Figma por separado de las anotaciones nativas posteriores de Figma, además de los contratos completos de componentes y modos de variables.

  • El Registro de Enlaces de Diseño otorga a un componente, pantalla o marco un id de Entidad de Diseño duradero y propiedad del repositorio. figma-bridge.json contiene enlaces portátiles de código/Storybook/Figma; los datos del plugin de Figma contienen solo el mismo id y tipo. Este anclaje dual permite que futuros agentes resuelvan el componente existente exacto desde cualquier lado sin poner rutas de repositorio en un documento de Figma.

  • El Planificador de Ida y Vuelta (solo informe) compara el código actual y el subárbol de Figma normalizado actual con una Línea Base de Diseño Aceptada explícita. El Contexto de Diseño del Proyecto proyecta ese estado, los enlaces de entidad y las siguientes lecturas exactas a través de una Aplicación de Comandos en proceso. Cuando existen rutas semánticas, los subárboles modificados se informan con sus ids de nodo actuales; los marcadores de plugin en sí mismos nunca cuentan como cambios visuales.

  • Un Contrato de Diseño convierte la Captura de Diseño completa de una Entidad de Diseño vinculada en una puerta de repositorio determinista. Ejecute figma_run ["contract", "capture","ui.button"] una vez y revise el JSON; luego figma_run ["contract","check","ui.button"] informa de la deriva canónica y aplica por separado matrices de variantes, pisos de vinculación de tokens, tolerancias geométricas y transiciones de prototipo. Los identificadores volátiles de Figma se ignoran y las capturas con profundidad limitada se rechazan.

  • Un Catálogo de Capacidades resuelve cada Comando de Figma que ingresa a través de MCP en un plan inmutable antes de que cualquiera de los adaptadores de ejecución lo ejecute. Ese plan es la única fuente para exposición, efectos de Figma/espacio de trabajo/estado compartido, necesidad de objetivo, confirmación, rutas normalizadas, reintento, tiempo de espera, códigos de salida aceptados e identidad de trabajo en segundo plano. Los comandos desconocidos son rechazados.

Herramienta

Propósito

figma_connect

Iniciar modo seguro, generar/mostrar la clave de acceso, imprimir pasos de configuración del plugin.

figma_status

Informar inmediatamente del estado del daemon local, plugin, archivo y clave; validateRest:true comprueba explícitamente el token REST opcional.

figma_pairing

Mostrar la clave de acceso; {rotate:true} genera una nueva.

figma_run

Ejecutar un comando de motor aprobado por el Catálogo de Capacidades; descúbralos con figma_reference {name:"capabilities"}.

figma_render

Renderizar JSX dentro del diseño de Figma abierto.

figma_inspect

Inspeccionar un nodo por id: geometría, rellenos/trazos/efectos, clip, opacidad (YAML).

figma_screenshot

Guardar un PNG de un nodo/selección en un archivo temporal (se devuelve la ruta + dimensiones + escala aplicada).

figma_spec

Especificación de diseño a código de un nodo: contenido real, nombres de componentes, tokens, referencias de arte vectorial, clip/abs — en fases.

figma_reference

Referencia offline de la API del Plugin de Figma (api setup una vez); {name:"capabilities"} lista el índice de comandos generados sin iniciar el motor.

figma_history

Historial de cambios locales del registro de auditoría — filtrar por nodeId, opcionalmente fusionar con git log de los archivos de código generados y (complemento REST) el historial real de versiones del archivo de Figma mediante includeVersions:true. O pasar diff:{from,to} para un diff estructural del propio documento (añadido/eliminado/reemplazado/movido/cambiado). figma_run/figma_render aceptan un label para anotar entradas.

figma_selection

La selección actual del usuario en Figma (ids, nombres, tipos, tamaños) — enviada en vivo por el plugin. Las instancias resuelven a su key de publicación estable; los nodos enlazados muestran su Entidad de Diseño, archivo de código e historia de Storybook.

figma_comments

Complemento REST: leer comentarios de revisión de diseño (action:"list") o publicar/responder (action:"post" — siempre muestra vista previa primero, necesita confirm:true).

Los ids de nodo se aceptan en cualquier forma que el usuario tenga a mano: 12:34, la forma de URL 12-34, o una URL completa de Figma (cuya clave de archivo se comprueba con los archivos que realmente tiene abiertos — consulte Varios archivos a la vez).

Los comandos de escritura se pueden bloquear detrás de un confirm:true explícito estableciendo FIGMA_WRITE_CONFIRM=1 en el entorno del servidor. El bloqueo funciona a nivel de subcomando: las lecturas como node tree o component list pasan libremente, las mutaciones como node delete, combos o tokens spacing requieren confirmación.

Las instancias nativas de JSX requieren identidad de Registro duradera (entity más una key publicada o id local). Sus anulaciones editables utilizan la estructura real de Figma del componente:

<Instance entity="ui.card" key="..."
  prop:Selected="true"
  text:Title="New title"
  fill:StatusDot="var:status/healthy|#22c55e"
  swap:LeadingIcon="ui.icon.leaf" />

prop: resuelve una definición de propiedad de componente; text: y fill: resuelven un descendiente nombrado. Los valores de swap: y los valores de propiedad INSTANCE_SWAP son ids de Entidad de Diseño, resueltos desde figma-bridge.json; los nombres de visualización de los componentes no se aceptan intencionadamente como identidad de intercambio. Los destinos faltantes, ambiguos o no vinculados detienen la verificación previa antes de que se cree el primer nodo de lienzo.

Las dimensiones y la tipografía aceptan la misma forma var:nombre|fallback. El ejecutor nativo vincula ancho, alto y restricciones min/max, además de familia/estilo de fuente, peso, tamaño, altura de línea, espaciado entre letras, espaciado entre párrafos y sangría de párrafo. Familia/estilo utilizan variables STRING; los otros campos de tipografía y dimensión utilizan variables FLOAT. Una fuente vinculada faltante detiene la verificación previa con un mensaje de instalar-o-elegir-otra en lugar de sustituirla silenciosamente. Los Estilos de Texto nombrados también se reconcilian antes de la creación del lienzo: un style="Typography/Eyebrow" explícito se reutiliza solo cuando su tipografía completa coincide; un estilo del mismo nombre conflictivo se detiene, y de lo contrario la tipografía exacta se reutiliza o se crea bajo un nombre determinista Typography/Generated/.... La lectura de la métrica float32 de Figma se normaliza para una comparación estable, y las caras específicas de familia como DM Sans/Manrope SemiBold y ExtraBold se prueban antes que cualquier familia de respaldo. Los renderizados nativos exitosos devuelven recuentos de textStyleReport y variableReport para referencias, variables reutilizadas únicas, variables creadas y propiedades vinculadas. Los errores de verificación previa ambiguos o no compatibles incluyen los recuentos cero/no cero correspondientes y no dejan variables recién creadas o nodos de lienzo atrás.

<Text> también conserva el Texto Enriquecido en línea editable. El marcado anidado <strong>/<b>, <em>/<i>, <u>, <Span ...> y <a href="..."> se convierte en rangos nativos de Figma; las entidades HTML se decodifican antes de calcular los desplazamientos de rango UTF-16. Los tramos Span admiten font, fontStyle, weight, italic, size, color, letterSpacing, underline/decoration y enlaces seguros:

<Text font="Inter" size="14">
  Hello <strong>bold <em>and italic</em></strong>
  <Span color="#ef4444" size="18">red</Span>
  <a href="https://example.com">link</a>
</Text>

Ventana del plugin

La ventana del plugin Figma Bridge es más que el estado de la conexión:

  • Actividad — cada comando que ejecuta el agente, en vivo, con duración y ok/error; las escrituras se resaltan. La fila colapsada lleva el recuento (12 ok · 1 falló); el puerto conectado y la latencia de ida y vuelta están en la barra de título.

  • Pausar agente — un interruptor de apagado: mientras está en pausa, el plugin rechaza cada comando entrante del agente con un error explícito.

  • Guardar versión — escribe una entrada etiquetada en el historial de versiones propio de Figma (Figma Bridge — <timestamp>) como un punto de restauración manual antes de dejar libre al agente. No hay API de restauración para plugins: se retrocede a través del panel de historial de versiones de Figma.

  • Lectura de selección — lo que sea que el usuario seleccione se envía al agente automáticamente (con debounce) y se muestra como "El agente ve: …", de modo que el usuario siempre ve lo que devolverá figma_selection. Seleccione un marco, diga "construye esto" — sin copiar ids de nodo.

  • Configuración — clave de acceso y el token REST opcional, siempre accesible independientemente de si el puente está conectado.

Flujo de trabajo de diseño a código

El diseño es la especificación completa — las herramientas facilitan copiarlo en lugar de interpretarlo. Construya una pantalla desde Figma en seis pasos:

Mantenga el framework y el sistema de estilos del proyecto destino. No agregue Tailwind, un kit de UI o una biblioteca de iconos únicamente para la pantalla, y nunca reemplace el arte de Figma exportado con una aproximación conveniente. Reutilice un componente del proyecto solo cuando su diseño renderizado y sus estados realmente coincidan.

  1. figma_screenshot en el frame objetivo, luego lee el PNG guardado — la verdad visual de referencia. Nunca construyas solo a partir del árbol de nodos.

  2. figma_spec con phase: "structure" — construye el esqueleto del marcado: caracteres de texto reales, nombres de iconos/componentes resueltos (se desciende a las instancias, por lo que aparecen las sobrescrituras y los nombres reales del componente principal), jerarquía y dirección flex. Copia textos e iconos textualmente. Un marcador layout:inferred (Figma heuristic — verify) no es Auto Layout creado; verifica la jerarquía antes de tratarlo como el contrato del componente.

  3. Exporta tokens (figma_run con ["export","css"] o ["export","dtcg"]) y conéctalos como variables CSS / tema. La salida nombra su archivo Figma de origen — verifica que es el archivo que estás construyendo.

  4. Exporta assets (figma_run con ["export","assets","<nodeId>","-o","/abs/path/src/assets"]) — cada referencia → assets/… en la especificación apunta a un archivo que esto escribe. Pasa una ruta absoluta; las exportaciones grandes siguen ejecutándose en segundo plano ("still RUNNING") — vuelve a ejecutar la misma llamada para sondear. assets.json se fusiona entre ejecuciones y los activos byte-idénticos se deduplican. Cada entrada lleva datos de colocación (desplazamientos x/y, ruta de nombre del parent, parentId, absolutePosition, overhang), por lo que el manifiesto por sí solo posiciona una superposición — no se necesita referencia cruzada de la especificación. El resumen de exportación lista explícitamente los archivos posicionados absolutamente y con voladizo: esos son los que las compilaciones pierden. Los PNG sobredimensionados se reducen por defecto a 2× su uso más grande en Figma (densidad retina), sin escalado ascendente y solo cuando el archivo codificado se vuelve más pequeño. La relación de aspecto, la colocación en el manifiesto y el comportamiento de recorte CSS permanecen sin cambios; pasa --raster-scale 0 para conservar los bytes PNG originales.

  5. figma_spec con phase: "style" — aplica tamaños, espacios, relleno, alineación, dimensionamiento fill/hug, pinturas incl. degradados (→ var(name) marca un enlace a token de diseño), radios, sombras, tipografía, opacity, clip (overflow hidden) y posicionamiento abs. Los vectores decorativos aparecen como líneas vector art → assets/… con colocación — coloca los SVGs exportados, nunca los aproximes en CSS.

    El YAML/JSON estructurado además conserva las definiciones y valores exactos de las propiedades del componente (incluyendo INSTANCE_SWAP y SLOT), referencias a propiedades, valores preferidos, sobrescrituras directas, instancias expuestas y violaciones de slot. Los enlaces de variables incluyen identidad de colección, ámbitos creados, modos explícitos/resueltos, codeSyntax.WEB y el valor resuelto; inferredVariables se emite por separado como evidencia solo de sugerencia.

    Para una sección grande, solicita primero depth:0. Este es un contrato completo para el contenedor de la sección en sí (incluyendo fondo, borde, radio y diseño) sin descendientes. Luego solicita los ids de nodos hijos en llamadas acotadas. Usa dedup:true para tarjetas/listas repetidas; las referencias compartidas S<n> permanecen sin pérdida y evitan que los estilos de instancias idénticas agoten el presupuesto de resultados.

  6. Verifica — captura la pantalla de tu compilación y compárala con el PNG del paso 1, luego ejecuta la comprobación mecánica:

    figma_run ["verify-build", "/abs/path/to/project"]

    Busca en el proyecto contra assets.json y lista cada archivo exportado que no está referenciado en la compilación — con tamaño, desplazamientos y padre, por lo que colocarlo es un paso — más un lint de border-image (CSS border-image ignora border-radius; los trazos degradados en cajas redondeadas necesitan el patrón de envoltorio o máscara). Código de salida 1 cuando faltan archivos, por lo que también funciona como puerta de CI.

    Con una captura de pantalla de la compilación también ejecuta la pasada visual:

    figma_run ["verify-build", "/abs/path/to/project", "--compare", "/abs/build.png"]

    El render de referencia se obtiene en vivo de Figma (--node <id>, por defecto: la raíz de exportación del manifiesto) o se suministra sin conexión mediante --design <png>. Ambas imágenes se normalizan a un ancho común y se comparan píxel a píxel (tolerante al antialiasing); la salida informa el porcentaje de diferencia general, un hallazgo de desajuste de altura (compilación demasiado alta/baja = bloque insertado o eliminado), las peores regiones de diferencia en coordenadas de píxeles del nodo — el mismo espacio que usan la especificación y assets.json — y escribe un PNG de diferencias (rojo = diferente, sobre el diseño atenuado). Informativo por defecto; --max-diff <pct> controla el código de salida.

Para pantallas grandes, los agentes a nivel de sección son una optimización opcional del tiempo transcurrido después de que la captura de pantalla, el mapa de estructura, los tokens y los activos estén fijos. Úsalos solo para secciones sustanciales con archivos de componentes/estilos disjuntos; el coordinador mantiene la propiedad del shell compartido, los tokens, assets.json, la integración y la diferencia de píxeles final. Los agentes paralelos suelen consumir más tokens totales porque cada uno necesita contexto del proyecto, por lo que usa trabajo secuencial cuando el costo de tokens importa más que el tiempo de reloj.

Usa una herramienta de navegador existente o un arnés de proyecto para la captura de pantalla de la compilación. No instales Playwright (u otra dependencia de navegador) únicamente para la captura sin la aprobación del usuario; si ya está presente, es un mecanismo de captura válido en lugar de una dependencia de Figma Bridge.

La misma especificación está disponible como figma_run ["export", "code-spec", "<nodeId>"]. Su valor predeterminado es el árbol legible; pasa -f yaml o -f json para el modelo canónico.

Lossless structured spec formats

figma_spec y export code-spec tienen por defecto format:"tree", la vista de agente concisa y orientada a líneas cuyos pies llevan las acciones requeridas de activos y fidelidad. Usa yaml o json formateado explícitamente cuando un consumidor necesite el modelo canónico versionado. Ambos formatos estructurados serializan el mismo modelo; solo difiere la sintaxis. Las pruebas de ida y vuelta requieren que cada campo — texto, ids, procedencia del diseño, pintura, tipografía, variables sensibles al modo, activos, contratos de componentes, intención de Bridge, anotaciones nativas, integridad de captura y comprobaciones de fidelidad — sobreviva exactamente. No se ofrece JSON minimizado: pruebas reales con agentes mostraron que una sola línea enorme era materialmente más difícil de procesar a pesar de llevar los mismos campos sin procesar.

El campo capture del modelo informa explícitamente la profundidad solicitada/real, la integridad de la carga útil, la política de nodos ocultos y si la profundidad solicitada cortó descendientes. No hay truncamiento silencioso del resultado de la herramienta: si una especificación excede el presupuesto de salida configurado, la llamada devuelve complete:false con una receta de reintento sección por sección y devuelve ningún diseño parcial engañoso. depth:0 intencionalmente significa “solo el nodo solicitado” y es completo, no un árbol truncado en profundidad.

Los nombres de archivo de relleno IMAGE se indexan por el hash de imagen estable de Figma, no por el nombre/ruta de la capa local. Esto mantiene figma_spec, llamadas aisladas a hijos, exportación de activos y assets.json en el mismo nombre de archivo incluso cuando capas genéricas como “Frame 64” se alcanzan a través de diferentes raíces.

Para llamadas MCP de diseño a código, dedup:false es el valor predeterminado: cada capa visible mantiene su propio id, css{…} nativo de Figma Inspect, hechos de diseño/pintura/token y texto completo. Las capas de texto enriquecido mixto llevan sus rangos con estilo individuales. El pie de página concilia el recuento de capas visibles en vivo con filas explícitas, internos SVG, internos de componentes y ayudantes no renderizables. Se rechaza una proyección de estilo cuando los límites de profundidad o una capa no contabilizada forzarían la adivinación; divídela por los ids de nodo del mapa de estructura. Establece dedup:true solo para una vista general compacta usando referencias de estilo y repetición compartidas S<n>.

Para llamadas repetidas a nodos explícitos, phase, format y la deduplicación no desencadenan otra caminata completa de Figma. La caché en memoria de Design Capture está limitada a 8 entradas / 8 MiB por defecto (DESIGN_CAPTURE_CACHE_ENTRIES y DESIGN_CAPTURE_CACHE_BYTES). Cada acierto aún sondea la revisión del documento en vivo; no hay TTL ni ruta stale-while-revalidate.

Code ↔ Figma design memory

Asigna a cada componente, pantalla o frame importante un id de Entidad de Diseño duradero. El id describe el concepto, no su ubicación actual: usa nombres como ui.button, ui.account-card o screen.settings.

Después de seleccionar o identificar un nodo de Figma, un agente puede crear el enlace con:

figma_run {args:["link","set","9:9","screen.settings","--kind","screen","--source","src/routes/settings.tsx","--export","SettingsScreen","--story","screens-settings--default"], confirm:true}

Esto converge dos pequeños adaptadores:

  • figma-bridge.json es el Registro confirmado y revisable con rutas de código relativas al repositorio más manejadores opcionales de Storybook y Figma.

  • Figma almacena solo {version,id,kind} como datos de plugin en el nodo. No contiene ruta local, credencial ni estado específico de la máquina.

Usa figma_run ["link","inspect","9:9"] para resolver un nodo y figma_run ["link","list"] para inspeccionar la memoria del repositorio sin leer Figma. Una vez vinculado, figma_selection y figma_spec exponen automáticamente el mismo id y los objetivos de código/Storybook del Registro. Los agentes deben reutilizar o editar ese componente de código en lugar de crear uno similar. Repetir el mismo comando set es seguro y repara cualquiera de los lados después de una escritura interrumpida.

Después de verificar visualmente que el código y Figma corresponden, registra explícitamente sus huellas actuales. Las entidades de pantalla requieren una captura de pantalla real del navegador y un umbral de píxeles aprobado:

figma_run ["link","accept","screen.settings","--compare","/abs/build.png","--max-diff","5"]

El código fuente nunca se almacena en el Registro. El Adaptador de código inicial hashea el archivo vinculado completo más su identidad de exportación; por lo tanto, una edición no relacionada en un archivo compartido puede informar conservadoramente un cambio de código, pero un cambio real nunca se oculta. El Adaptador de Figma hashea el subárbol vinculado normalizado. Para nodos de Código a Figma también almacena cada figmaBridge.semanticPath único con el hash del subárbol de ese nodo. Un link status posterior puede por lo tanto listar las rutas semánticas exactas añadidas, eliminadas o cambiadas y recomendar especificaciones con ámbito de nodo. Cambiar solo un marcador semántico no cambia la huella visual; las rutas duplicadas se informan como ambiguas en lugar de adivinadas.

figma_run ["link","status","screen.settings"]
figma_run ["link","context","screen.settings"]

Estado

Significado

unchanged

Ningún lado se movió de la línea base aceptada.

code-only

Solo se movió el archivo de código vinculado.

figma-only

Solo se movió el subárbol de Figma vinculado.

conflict

Ambos se movieron; ningún lado se sobrescribe.

untracked

Aún no se ha aceptado explícitamente ninguna línea base.

link context es el punto de entrada preferido del agente después de que existe un enlace. Devuelve la proyección relevante más pequeña: entidad, código/exportación, raíz de Figma, historia de Storybook, Plan de Ida y Vuelta actual, archivos DESIGN.md/tokens descubiertos y próximas lecturas exactas. Se genera bajo demanda, no se persiste como otro archivo de memoria. link accept escribe solo figma-bridge.json; nunca cambia Figma ni el código. Para pantallas también almacena la diferencia medida y los hashes SHA-256 de ambas imágenes de comparación, por lo que una huella estructural no puede certificar una línea base visiblemente incorrecta.

Las ubicaciones convencionales de DESIGN.md, design/DESIGN.md, tokens.json y design/tokens.json se descubren automáticamente. Configura ubicaciones personalizadas relativas al repositorio una vez cuando sea necesario:

figma_run ["link","configure","--design-doc","docs/product-design.md","--tokens","src/theme/tokens.json"]

Haz commit de figma-bridge.json. No pongas secretos, rutas absolutas ni credenciales generadas en él. El esquema y las reglas de conflicto están documentados en docs/adr/0007-dual-anchor-design-entities.md, con decisiones de línea base y contexto en ADR-0008 y ADR-0009.

Reviewed CSS ↔ Figma boundary strategies

El Código Semántico a Figma usa ids de política estables en lugar de sustituciones visuales silenciosas: minmax.native-grid, space-around.equal-slots, border.single-paint-native, sticky.metadata-only, filters.layer-stack, masks.vector-mask, font.named-faces, y figma-effects.native. La matriz completa y sus paradas duras restantes están en docs/css-figma-semantic-matrix.md.

Las políticas revisadas que pierden cobertura pueden optar por una anotación nativa automática en Figma sobre el nodo semántico afectado exacto. La anotación explica el hecho CSS no compatible, enlaza las propiedades relevantes de Figma y se refleja como datos de plugin figmaBridge.fallbackAnnotations versionados para agentes futuros. Las conversiones nativas equivalentes permanecen sin anotar para evitar ruido en la revisión. La primera política activa es border.single-paint-native: Figma recibe el primer lado CSS pintado explícitamente como el trazo nativo compartido, conserva los cuatro pesos laterales y marca strokes más strokeWeight. Los renders nativos informan cuántas anotaciones de respaldo se agregaron, se deduplicaron o no fueron compatibles.

El texto DOM intrínseco de una sola línea se asigna al tamaño HUG de Figma. El texto posicionado y multilínea mantiene la geometría de caja medida; el puente no añade un margen porcentual arbitrario de ancho para evitar el ajuste de línea.

Los ejes de fuentes variables se capturan, pero la puerta estructural pregunta si la fuente requerida debe instalarse o si se debe usar un rostro con nombre disponible antes de renderizar. El Glass nativo de Figma sigue siendo un efecto nativo editable con todos los parámetros de efecto conservados; no se trata silenciosamente como CSS backdrop-filter, porque la exportación CSS de Figma no expone esos parámetros de Glass.

Espejo de Storybook

Los componentes de Figma llevan una clave de publicación estable (sobrevive a la publicación de la biblioteca; los ids de nodo son locales al archivo). La clave ahora fluye a través de figma_spec (modelo estructurado canónico + el tráiler de árbol "Conjuntos de componentes utilizados"), figma_selection, component list, figma_inspect y DESIGN.md.

Para vincularlos con su espejo de código:

figma_run ["map", "storybook", "http://localhost:6006"]

Esto compara los componentes del archivo con el índice de Storybook por nombre normalizado y escribe figma-map.json en tu proyecto: clave de Figma ↔ id de historia / ruta de importación, con una confidence por coincidencia más ambas listas no coincidentes. Edita las entradas a mano y establece "matchedBy": "manual" para fijarlas; las entradas fijadas sobreviven a las re-ejecuciones. Cuando el archivo existe, figma_selection y figma_spec anotan los componentes con ↔ story <id> (<importPath>) automáticamente.

figma-map.json sigue siendo un adaptador de lectura heredado, por lo que las asignaciones existentes continúan funcionando. Los nuevos enlaces duraderos pertenecen a figma-bridge.json; link set nunca copia filas heredadas en él. Migra un componente la próxima vez que lo toques asignándole su id real de Entidad de Diseño y pasando su historia mediante --story. Elimina el archivo heredado solo después de que link list muestre todas las asignaciones que aún necesitas.

Trae tu propio sistema de diseño

Este proyecto no incluye ningún sistema de diseño — ni shadcn, ni preset de Tailwind, ni paquete de iconos. Eso es deliberado: un sistema empaquetado es la opinión de alguien más renderizada en tu archivo. Lo que incluye en su lugar es una forma de hacer legible tu sistema para un agente en un solo comando:

figma_run ["kit", "init", "./my-app", "--storybook", "http://localhost:6006"]

Cuatro lecturas, un informe:

Paso

Resultado

extract

design/DESIGN.md — estructura, tokens, matrices de variantes

export dtcg

design/tokens.json — tokens de diseño W3C

component list --all-pages

inventario con claves de publicación estables

map storybook

figma-map.json — componente de Figma ↔ historia

Termina nombrando lo que aún falta — un Storybook no mapeado, componentes sin historia, el comando tokens sync que mantiene ambos sincronizados — porque una configuración que silenciosamente carece del mapeo parece terminada hasta que un agente la necesita.

DESIGN.md es lo que un agente debería leer primero; tokens.json es a lo que se vincula.

Varios archivos a la vez

El puente mantiene una conexión por ventana de Figma en la que iniciaste el plugin. Ese es el modelo de consentimiento: un archivo es accesible porque lo abriste e iniciaste el plugin allí — no porque una bandera amplió el alcance.

  • Una ventana — nada cambia. Los comandos van allí.

  • Varias ventanas — un comando debe nombrar su objetivo, o falla con la lista de archivos conectados:

    figma_status                                        # lists every connected window
    figma_run {args: ["canvas","info"], fileKey: "GY5SasBJ…"}
    figma_spec {nodeId: "12:34", fileKey: "GY5SasBJ…"}

    figma_render, figma_selection, figma_inspect, figma_screenshot y figma_spec aceptan el mismo parámetro fileKey. Una URL de nodo de Figma completa también proporciona su clave de archivo automáticamente. Sin un objetivo, figma_selection indica qué archivos están abiertos en lugar de adivinar. En la CLI del motor la bandera es --figma-file, no --file: eval y spec ya usan -f, --file para una ruta local.

Deliberadamente no hay opción "todos los archivos". Cada escritura nombra un archivo, por lo que un comando equivocado no puede propagarse a través de una biblioteca. Dos ventanas en el mismo archivo son indistinguibles para el enrutamiento, por lo que la más nueva toma el control y a la más antigua se le informa que perdió el puente. Las entradas de auditoría llevan la clave del archivo, por lo que figma_history sigue siendo legible cuando hay varios archivos en juego.

Alcanzar archivos que no has abierto está fuera del alcance: la API REST de Figma no puede escribir contenido de documento, por lo que un cambio de nombre masivo en treinta archivos de biblioteca no es algo que esta herramienta pueda ofrecer honestamente.

FigJam

El plugin también se ejecuta en tableros FigJam, sobre el mismo puente — sin segundo transporte, sin permiso adicional:

figma_run ["jam", "sticky", "Ship the handshake", "--color", "green"]
figma_run ["jam", "stickies", "[\"Discovery\",\"Build\",\"Ship\"]", "--columns", "3"]
figma_run ["jam", "shape", "Decide?", "--type", "DIAMOND"]
figma_run ["jam", "connector", "1:2", "3:4", "--text", "yes"]
figma_run ["jam", "table", "3", "4", "--data", "[[\"Step\",\"Owner\"],[\"Handshake\",\"Alex\"]]"]
figma_run ["jam", "board"]      # read everything back, with connectors
figma_run ["jam", "arrange"]    # arrange only the current selection
figma_run ["jam", "arrange", "--ids", "1:2,3:4"]
figma_run ["jam", "arrange", "--all"] # explicit: whole page

Los nuevos nodos se colocan a la derecha de lo que ya esté en el tablero a menos que pases --at x,y, por lo que un agente que añade a un tablero poblado no apila todo en el origen. Cada comando verifica primero figma.editorType y dice "esto es un archivo de Figma, no un tablero FigJam" en lugar de fallar en una API indefinida. figma_status informa a qué editor está conectado el puente.

jam arrange está deliberadamente limitado al ámbito de la selección. Los agentes pueden pasar ids de nodo exactos sin cambiar la selección del usuario; reorganizar toda la página requiere el flag visible --all. Las secciones y conectores nunca son movidos por este comando. La superficie pública se probó en Figma Desktop el 2026-08-10. Los mantenedores conservan el comando detallado y la evidencia de relectura fuera del repositorio público.

Beta de Figma Slides

Slides utiliza el mismo puente de plugin autenticado. La superficie beta cubre la estructura de la presentación y las propiedades nativas de las diapositivas, no un renderizador de presentaciones separado:

figma_run ["slides", "inspect"]
figma_run ["slides", "create", "Agenda", "--row", "0", "--col", "1"]
figma_run ["slides", "duplicate", "Agenda", "--label", "Agenda alternative"]
figma_run ["slides", "move", "Agenda alternative", "1", "0"]
figma_run ["slides", "transition", "Agenda", "DISSOLVE", "--duration", "0.4"]
figma_run ["slides", "skip", "Appendix", "on"]
figma_run ["slides", "delete", "1:42"]

Figma renombra los nombres nativos de las diapositivas cada vez que cambia la cuadrícula del lienzo. El argumento opcional para create y --label en duplicate por lo tanto almacenan una etiqueta Bridge duradera en los datos del plugin; inspect informa tanto el name nativo como la label estable. Las referencias se resuelven por id, nombre nativo exacto o etiqueta, luego subcadena única. La ambigüedad es un error, delete siempre requiere una referencia explícita, y duplicate/move rechazan una fila de destino inexistente en lugar de aceptar la colocación de respaldo de Figma. Cada operación verifica figma.editorType === "slides" antes de tocar una API exclusiva de Slides. Los candidatos abiertos y los criterios para salir de beta residen en docs/slides-roadmap.md; la aceptación del editor es verificada por los mantenedores por separado del repositorio público.

Sincronización de tokens (bidireccional)

tokens import solo crea, por lo que un valor editado en código nunca llega a una variable de Figma existente y un valor editado en Figma nunca llega al código. tokens sync cierra ese bucle:

figma_run ["tokens", "sync", "src/tokens.json"]              # plan only
figma_run ["tokens", "sync", "src/tokens.json", "--apply"]   # write it

La superficie de importación es más amplia que la superficie de sincronización. El import de una sola vez acepta configuraciones de Tailwind v3, Tailwind v4/CSS, índices de Storybook, JSON DTCG/W3C y las formas de tokens compatibles con DTCG exportadas por Style Dictionary y Tokens Studio. Esa compatibilidad no incluye semántica de temas de Tokens Studio ni preprocesadores arbitrarios; los metadatos como $themes se ignoran mientras se leen los conjuntos de tokens y alias.

Las nuevas variables FLOAT en espacios de nombres explícitos spacing/* o space/* se limitan a los consumidores GAP de Figma solamente. Las variables radius/* y radii/* se limitan a CORNER_RADIUS solamente. La inferencia es deliberadamente exacta al espacio de nombres: nombres como spacingFactor se dejan en el ámbito predeterminado de Figma, y el renderizado no cambia silenciosamente los ámbitos de las variables de usuario o biblioteca existentes. Otras nuevas variables COLOR, FLOAT o STRING muestran SCOPE DECISION REQUIRED con solo las opciones de Figma compatibles. El agente debería preguntar antes de reducirlas; inspecciona el catálogo con figma_reference {name:"variable-scopes"} y aplica la respuesta con figma_run ["var","update","<name>","--collection","<collection>","--scopes","TEXT_FILL,STROKE_COLOR"].

La sincronización segura a tres bandas acepta solo tokens de diseño DTCG / W3C (.json, lo que emite export dtcg) y propiedades personalizadas CSS (.css, lo que emite export css). Las $variables de Sass no son propiedades personalizadas CSS y se rechaza .scss en lugar de analizarlo parcialmente. Ten en cuenta que export dtcg escribe todas las variables locales en un archivo mientras que la sincronización apunta a una colección — pasa --collection en consecuencia. Si la mayoría de los nombres en el archivo ya viven en otra colección, la sincronización lo dice en lugar de ofrecer duplicarlos. Las configuraciones de Tailwind son solo una fuente de importación — su analizador agrupa valores en color/espaciado/radio y no puede hacer un viaje de ida y vuelta, por lo que la sincronización las rechaza por nombre en lugar de eliminar silenciosamente tokens que no entendió.

Por qué un archivo de bloqueo. Una sincronización bidireccional sin memoria no puede distinguir "el código cambió" de "Figma cambió" — solo ve que los dos difieren, y la dirección que elija destruye el trabajo del otro lado. figma-tokens.lock.json registra el estado en la última sincronización exitosa, por lo que cada decisión es una comparación a tres bandas:

código

Figma

resultado

cambió

sin cambios

actualizar Figma

sin cambios

cambió

reportado, nunca sobrescrito — actualiza tu archivo de código

ambos cambiaron

conflicto — no se aplica nada

sin cambios

sin cambios

sin cambios

Los conflictos detienen toda la ejecución. Resuélvelos editando un lado, o decídelos todos a la vez con --ours (gana el archivo de código) / --theirs (gana Figma, y no se escribe nada en Figma).

Las eliminaciones necesitan --prune, y aún así solo tocan variables que la propia sincronización creó — una variable que nunca rastreó se reporta como no rastreada y se deja intacta.

El archivo de bloqueo también almacena el id de Figma de cada variable, que es lo que convierte un cambio de nombre en un cambio de nombre en lugar de un borrar más un crear que perdería todos los enlaces de capa. El emparejamiento es por valor y solo cuando no es ambiguo: cambiar el nombre y el valor de un token en el mismo commit vuelve a crear + borrar, así que haz esos dos pasos si los enlaces importan.

Sin --apply el comando sale con código 1 cuando hay cambios pendientes, por lo que funciona como una verificación de CI para "¿está Figma sincronizada con el repo?".

Vinculación, y cambiar qué colección sigue un diseño

tokens sync escribe valores de token. Dos cosas vecinas que deliberadamente no hace:

figma_run ["node", "bind", "12:34", "radius", "radius/lg", "--collection", "TARGET_COLLECTION"]
figma_run ["tokens", "rebind", "TARGET_COLLECTION", "--node", "12:34"]            # plan
figma_run ["tokens", "rebind", "TARGET_COLLECTION", "--node", "12:34", "--apply"] # write

node bind adjunta una variable a una propiedad de un nodo existentefill, stroke, radius, gap, padding (o un lado), opacity, stroke-width, width, height. Su contraparte de lectura es node bindings. Pasa --batch con un array JSON para vincular muchas propiedades o nodos en una sola llamada.

Un nombre de variable que no es único es rechazado, no adivinado — este archivo tiene radius/lg en dos colecciones, y la respuesta nombra ambas para que --collection pueda resolverlo. El tipo de la variable se verifica contra la propiedad primero, por lo que un COLOR en radius falla con una oración en lugar de un rastro de pila del plugin.

Las variables de tipografía tienen su propio comando con reconocimiento de rango porque el texto puede llevar diferentes vinculaciones en diferentes intervalos de caracteres:

figma_run ["font", "bind", "12:36", "fontWeight", "type/weight", "--collection", "Typography"]
figma_run ["font", "bind", "12:36", "line-height", "type/line-height", "--start", "0", "--end", "12"]
figma_run ["font", "unbind", "12:36", "lineHeight", "--start", "0", "--end", "12"]

Los campos enlazables son fontFamily, fontSize, fontStyle, fontWeight, letterSpacing, lineHeight, paragraphSpacing y paragraphIndent; también se aceptan las grafías en kebab-case. Las fuentes existentes —y para los enlaces de familia/estilo/peso los estilos de familia disponibles relevantes— se cargan antes de que se cambie el enlace. Los nombres de variables se rechazan cuando son ambiguos, y se comprueba STRING vs FLOAT antes de llamar a Figma. Un enlace numérico de fontWeight sigue sin ser un asignador general de ejes de fuentes variables: Figma selecciona un peso válido para la fuente activa.

tokens rebind es el cambio de tema: recorre un subárbol y reasigna cada enlace a la variable del mismo nombre en una colección destino. Diseña una tarjeta contra SOURCE_COLLECTION, ejecuta rebind con TARGET_COLLECTION, y la misma tarjeta sigue los valores de la colección destino — sin rediseño. Por defecto planifica; --apply escribe. Los tokens sin contraparte en el destino se listan y se dejan apuntando donde estaban, así que un tema parcial es un informe, no un diseño a medio estropear.

node set cambia propiedades en nodos que ya existen — fill, stroke, strokeWidth, radius, opacity, x, y, width/height, name, visible — un nodo a la vez o muchos mediante --batch, lo cual importa porque la forma por lotes es un viaje de ida y vuelta:

figma_run ["node", "set", "12:34", "--name", "Card", "--radius", "12"]
figma_run ["node", "set", "--batch", "[{\"node\":\"12:35\",\"fill\":\"var:sage/50\",\"name\":\"Badge\"}]"]

Un color acepta un hex o var:<name>. La diferencia no es cosmética: un hex está congelado, una referencia var: permanece enlazada, por lo que un posterior tokens rebind puede moverla aún.

Estilos locales, metadatos de variables y modos

Las primitivas locales del sistema de diseño que antes requerían trabajo manual en la UI ahora tienen Figma Commands de primera clase. Utilizan la API de Plugin en vivo, no REST:

figma_run ["style", "list", "--type", "TEXT"]
figma_run ["style", "show", "Heading/H1"]
figma_run ["style", "create", "PAINT", "Brand/Primary", "--properties", "{\"paints\":[{\"type\":\"SOLID\",\"color\":{\"r\":0.1,\"g\":0.3,\"b\":0.9}}]}"]
figma_run ["style", "apply", "Brand/Primary", "12:34,12:35", "--field", "fill"]
figma_run ["style", "consumers", "Brand/Primary"]
figma_run ["style", "publish-status", "Brand/Primary"]
figma_run ["style", "bind-font", "Body", "fontSize", "--variable", "type/size/body"]
figma_run ["style", "unbind-font", "Body", "fontSize"]

style cubre los estilos locales PAINT, TEXT, EFFECT y GRID. update acepta las mismas propiedades JSON específicas de tipo que create; apply valida el tipo de estilo contra fill, stroke, text, effect o grid. Las búsquedas por nombre rechazan ambigüedad. Los consumidores provienen de getStyleConsumersAsync(), y el estado de publicación es uno de los valores UNPUBLISHED, CURRENT o CHANGED de Figma.

Las variables exponen los metadatos y las operaciones de modo que la sincronización de archivos de tokens no posee:

figma_run ["var", "show", "space/md", "--collection", "Primitives"]
figma_run ["var", "update", "space/md", "--description", "Medium spacing", "--scopes", "GAP"]
figma_run ["var", "set-value", "space/md", "12", "--mode", "Light"]
figma_run ["var", "set-value", "space/card", "--alias", "space/md", "--mode", "Light"]
figma_run ["var", "code-syntax", "space/md", "WEB", "var(--space-md)"]
figma_run ["var", "resolve", "space/md", "12:34"]
figma_run ["col", "mode-add", "Primitives", "Dark"]
figma_run ["col", "mode-rename", "Primitives", "Dark", "Dim"]
figma_run ["col", "extend", "Primitives", "Brand"]

var show devuelve valores por modo, ámbitos, sintaxis de código, metadatos de colección y estado de publicación. var resolve requiere deliberadamente un nodo consumidor porque los alias pueden resolverse de manera diferente bajo los modos seleccionados de ese nodo. Las operaciones show, update, mode-add, mode-rename, mode-remove y publish-status de colección siguen la misma política de búsqueda por ID/nombre exacto/subcadena única. Los límites de Figma en la cantidad de modos permanecen impuestos por Figma y se manifiestan como errores. Las extensiones de colección usan VariableCollection.extend() para colecciones locales y extendLibraryCollectionByKeyAsync() para claves publicadas. Figma restringe esta característica a planes Enterprise; el CLI informa el error de plan de Figma sin cambios. Los enlaces de estilo de texto admiten exactamente los campos de tipografía enlazables de Figma: familia, estilo, peso, tamaño, altura de línea, espaciado entre letras y valores de párrafo.

Bibliotecas de equipo habilitadas

El descubrimiento e importación de bibliotecas también se mantienen en el transporte autenticado de plugins:

figma_run ["library", "collections"]
figma_run ["library", "variables", "Acme/Primitives", "--type", "COLOR"]
figma_run ["library", "import-variable", "<published-variable-key>"]
figma_run ["library", "import-style", "<published-style-key>"]
figma_run ["library", "import-component", "<published-component-key>"]
figma_run ["library", "import-component-set", "<published-component-set-key>"]

collections y variables son lecturas. Los cuatro comandos import-* materializan activos publicados en el archivo actual y, por lo tanto, son escrituras en el Catálogo de Capacidades. Figma solo expone el descubrimiento para colecciones de variables y variables. Los estilos, componentes y conjuntos de componentes publicados pueden importarse cuando su clave estable ya se conoce, pero la API de Plugin no puede enumerarlos.

Las bibliotecas deben estar habilitadas para el archivo actual en la UI de Figma antes de que library collections pueda verlas; la API de Plugin no puede habilitar una biblioteca. El plugin enviado ya declara el permiso teamlibrary requerido. La búsqueda de nombres usa la clave de colección, el nombre exacto de la colección y luego una subcadena inequívoca de colección o nombre de biblioteca. El descubrimiento de bibliotecas tiene un tiempo de espera de 18 segundos de la API de Plugin por debajo del límite de Bridge, por lo que una solicitud de biblioteca de Figma estancada nombra la operación y sugiere verificar si la biblioteca está habilitada en lugar de degradarse a un tiempo de espera de ejecución genérico.

Prototipos, mediciones en modo Dev y anotaciones

Estas características de documento también son prioritarias para la API de Plugin:

figma_run ["prototype", "inspect", "12:34"]
figma_run ["prototype", "add", "12:34", "--trigger", "click", "--navigate-to", "12:36"]
figma_run ["prototype", "set", "12:34", "--json", "[{\"trigger\":{\"type\":\"ON_CLICK\"},\"actions\":[{\"type\":\"BACK\"}]}]"]
figma_run ["measure", "add", "12:34:right", "12:36:left", "--offset", "16", "--text", "gap"]
figma_run ["annotate", "categories"]
figma_run ["annotate", "add", "Review spacing", "--node", "12:34", "--category", "Review", "--properties", "width,fontSize"]
figma_run ["annotate", "edit", "12:34", "0", "--text", "Resolved"]

prototype set --json es la forma sin pérdida para las múltiples acciones de Figma, SET_VARIABLE, SET_VARIABLE_MODE y bloques condicionales. Escribe a través de setReactionsAsync() por lo que se admiten manifiestos de página dinámica. Las escrituras de medición están protegidas para el modo Dev de Figma y usan los métodos de medición nativos de PageNode. Los índices de anotación son basados en cero; los comandos de crear/editar/eliminar categorías personalizadas están disponibles junto con categories. Estas notas de revisión manual son independientes de las Anotaciones de Límite de Retroceso automáticas del renderizador semántico, que se emiten solo mediante políticas de mapeo con pérdida explícitamente aceptadas y siguen siendo legibles por máquina a través de datos de plugin.

APIs de Plugin 2026: video, sombreadores, cuadrícula, slots y Draw

La superficie actual de la API oficial de Plugin se expone como Figma Commands en lugar de llamadas REST:

figma_run ["export", "video", "12:34", "--format", "mp4", "--fps", "30", "-o", "/abs/demo.mp4"]
figma_run ["shader", "list"]
figma_run ["shader", "import", "<shader-id>"]
figma_run ["shader", "apply", "12:34", "<shader-id>", "--field", "fill", "--properties", "{\"definition-id\":0.8}"]
figma_run ["layout", "grid", "set", "12:34", "--rows", "2", "--columns", "3", "--row-gap", "12"]
figma_run ["layout", "grid", "auto-flow", "12:34", "--auto-tracks", "rows", "--positioning", "row_auto_flow"]
figma_run ["slot", "create", "12:37", "Content", "--settings", "{\"minChildren\":1,\"maxChildren\":3}"]
figma_run ["slot", "validate", "12:37"]
figma_run ["draw", "inspect", "12:38"]
figma_run ["draw", "text-path", "12:38", "--text", "Around the curve"]
figma_run ["draw", "stroke-profile", "12:38", "--preset", "TAPER"]
figma_run ["draw", "pattern", "12:38", "12:39", "--field", "fill"]

La exportación de video resuelve un descendiente seleccionado a su fotograma animado de nivel superior y acepta solo los valores FPS específicos de formato de Figma. Las propiedades del sombreador se identifican por ID de definición, no por nombre para mostrar, y un sombreador disponible debe importarse antes de aplicarse. layout grid significa el modelo GRID de auto-layout; el comando grid de nivel superior anterior sigue siendo la gestión de guías de diseño. Los slots exponen SlotSettings en GA, valores preferidos, reinicio y violaciones de límite; JSX <Slot> ahora usa ComponentNode.createSlot() y valida los límites configurados después del renderizado. Los comandos Draw cubren trazados de texto, grupos de transformación repetidos, trazos stretch/scatter/dynamic, perfiles de ancho variable y setters asíncronos de relleno/trazo de patrón. Ejecuta las lecturas inspect/validate correspondientes antes de las escrituras al modificar un documento desconocido.

Encontrar lo que necesita reparación

figma_run ["analyze", "lint", "--node", "12:34"]

Una pasada para las cuatro cosas en las que actúa una revisión de sistema de diseño: colores que coinciden con una variable existente pero no están enlazados a ella, capas que aún llevan un nombre por defecto, texto sin estilo, texto por debajo de 12px. --fail-on-issues lo convierte en una puerta de CI; --kind lo acota; --json nunca trunca.

Un color codificado solo se informa cuando una variable ya tiene ese valor exacto — de lo contrario, el hallazgo es ruido sobre el que no se puede actuar. Debido a que la coincidencia se conoce, cada uno llega con el comando que lo repara:

unbound token colour — 1
  12:35    Badge  fill is #8a9a8d, which is sage/400
    fix: node bind 12:35 fill "sage/400" --collection "Sprout Primitives"

analyze colors|typography|spacing aún proporciona el censo completo. Lint es la pasada que responde si hay algo que hacer.

Fuentes variables y hechos OpenType

Figma no expone una tupla general de ejes de variación a través de la API de Plugin. Por lo tanto, el puente separa los hechos que Figma realmente informa de la intención de eje que un llamador registra explícitamente:

figma_run ["font", "inspect", "12:36"]
figma_run ["font", "inspect", "12:36", "--start", "0", "--end", "12", "--all-open-type"]

font inspect devuelve rangos de texto con estilo con fontName, fontWeight numérico de solo lectura, tamaño, etiquetas de características OpenType habilitadas y enlaces de variables de tipografía resueltas. --all-open-type también incluye valores de características falsos. El resultado nombra el límite de la API explícitamente: un fontWeight informado no es una tupla general wght/wdth/opsz/eje personalizado, y las características OpenType son de solo lectura.

Cuando los valores exactos del eje se conocen desde la UI u otra herramienta de fuentes, consérvalos en el nodo de texto como metadatos de rango:

figma_run ["font", "remember-axes", "12:36", "wght=357,wdth=82", "--start", "0", "--end", "12"]
figma_run ["font", "axes", "12:36"]
figma_run ["font", "forget-axes", "12:36", "--start", "0", "--end", "12"]
figma_run ["font", "forget-axes", "12:36"]  # clear every stored range

remember-axes cambia solo los metadatos del plugin — nunca la fuente o los glifos renderizados — y, por lo tanto, se clasifica como una escritura por el Catálogo de Capacidades. figma_spec lleva estos registros como axes-meta[inicio:fin](etiqueta=valor,…), más el valor fw… informado por Figma y las etiquetas ot(…) habilitadas, para que la captura de diseño a código no descarte silenciosamente la intención documentada.

Hechos nativos de la API de Plugin

Dos comandos de lectura exponen las representaciones propias de Figma sin contactar la API REST:

figma_run ["node", "css", "12:34"]
figma_run ["node", "css", "12:34", "--json"]
figma_run ["export", "node-json", "12:34"]
figma_run ["export", "node-json", "12:34", "-o", "facts/card.json"]

node css llama a getCSSAsync() y devuelve las declaraciones que Figma expone para su panel de Inspección. Esto está deliberadamente separado de export css, que exporta propiedades personalizadas de tokens de diseño. export node-json usa exportAsync({format:"JSON_REST_V1"}): la forma se asemeja al esquema de archivo REST, pero los bytes provienen del documento de plugin en vivo y no necesitan ni un token ni una solicitud de red.

Historial de versiones y diferencias

La API de plugin de Figma puede escribir una versión pero no leer una, por lo que "qué cambió desde esta mañana" no tiene respuesta solo desde el puente. history proporciona una sin ninguna credencial: registra la estructura de un subárbol, la registra de nuevo más tarde, compara las dos.

figma_run ["history", "save", "Before refactor", "--description", "Agent restore point"]
figma_run ["history", "snapshot", "--label", "before refactor"]
# … agent works …
figma_run ["history", "diff", "latest", "live"]

history save crea la entrada nombrada directamente a través de saveVersionHistoryAsync() y es una escritura de Figma. snapshot, list y diff siguen siendo operaciones de Figma locales/solo lectura; la lectura de las versiones históricas nativas de Figma aún requiere el complemento REST opcional.

Una instantánea almacena un registro normalizado por nodo — geometría, diseño, pinturas, tipografía, claves de componente — más un hash de contenido y un hash de subárbol, por lo que el comparador puede informar una sección no tocada en lugar de recorrerla. Viven en ~/.figma-bridge-mcp/snapshots/<fileKey>/, comprimidos con gzip, se mantienen los 20 más recientes.

Las referencias son latest, previous, un índice de history list, un nombre de archivo, o live para el documento en este momento. El informe separa añadido, eliminado, reemplazado, movido y cambiado — esa última distinción es la que importa en la práctica: un agente que elimina un marco y lo vuelve a renderizar mantiene la ruta del nombre pero obtiene nuevos ids de nodo, y sin la detección de reemplazo cada re-renderizado se leería como cien eliminaciones. --changelog emite markdown en su lugar; diff sale con 1 cuando algo difiere, por lo que también funciona como puerta de CI.

A través de MCP esto es un parámetro, no una decimotercera herramienta:

figma_history {diff: {from: "latest", to: "live"}}
figma_history {diff: {from: "version:1234", to: "version:5678"}}   # REST add-on

Las referencias version: pasan por la capa REST y comparan lo que los diseñadores guardaron, usando el mismo comparador. Las dos fuentes no pueden mezclarse en una sola diferencia: un documento REST y una instantánea de plugin exponen propiedades diferentes, por lo que cada nodo parecería cambiado — la herramienta lo dice en lugar de producir un muro de salida engañoso.

Motion

Figma Motion (Config 2026 Beta) es accesible a través de figma_run con ["motion", …]: pistas de fotogramas clave (add), especificaciones completas desde JSON (apply), preajustes con nombre (preset), desplazamientos coreografiados entre nodos (stagger), estilos de animación de primera parte de Figma (styles, style), duración de fotograma (timeline), lectura inversa (inspect) y eliminación (clear).

Como cualquier otro comando, se ejecuta sobre el puente del plugin — no hay un transporte separado para ello. styles e inspect son lecturas; todo lo demás, incluyendo timeline (lee o establece según sus argumentos), cuenta como escritura bajo FIGMA_WRITE_CONFIRM=1.

Motion se está implementando detrás de un indicador Beta de Figma. Sin acceso, los comandos fallan con un error MOTION_DISABLED con nombre que te dice que actualices Figma Desktop en lugar de un fallo genérico de API.

Complemento REST (opcional)

Todo lo anterior funciona con cero credenciales de Figma. Tres cosas que el puente de plugin local estructuralmente no puede alcanzar viven detrás de la API REST de Figma, y pueden desbloquearse con un token de acceso personal:

Característica

Qué añade

Historial de versiones

figma_history {includeVersions:true} fusiona lo que los diseñadores guardaron (cuándo, quién) en la línea de tiempo local de auditoría+git — la API del plugin solo puede escribir versiones, no leerlas. figma_history {diff:{from:"version:…", to:"version:…"}} va más allá y compara los propios documentos.

Comentarios

figma_comments lee las revisiones de diseño (con anclajes de nodo e ids de hilo) y puede responder. Publicar siempre muestra una vista previa primero y requiere confirm:true — los comentarios son visibles para otras personas.

Metadatos de biblioteca

map storybook enriquece automáticamente figma-map.json con la descripción de los componentes publicados y enlaces de documentación — una señal de coincidencia mucho más fuerte que la normalización de nombres.

Activación: el token nunca sale de tu máquina:

  1. Crea un token de acceso personal en Figma (Configuración → Seguridad → Tokens de acceso personal) con los ámbitos: Contenido del archivo (lectura), Versiones del archivo (lectura), Comentarios (lectura y escritura). Usuario actual (lectura) es opcional — solo hace que figma_status muestre tu nombre de usuario.

  2. Abre el plugin Figma Bridge en Figma Desktop, conéctate (el campo aparece una vez que el plugin está autenticado) y expande "REST token (opcional)". Pega el token, Guardar token.

  3. figma_status informa que el token está configurado sin hacer una solicitud remota. Ejecuta figma_status {validateRest:true} cuando quieras una verificación explícita de validez; informa tu nombre de usuario o verifica el acceso al archivo cuando el ámbito opcional Usuario actual está ausente.

El token viaja desde el plugin a través del WebSocket localhost autenticado hasta el demonio, que lo almacena en ~/.figma-bridge-mcp/rest-token (modo 0600). Nunca se introduce en el chat, nunca se almacena en la configuración de tu cliente MCP, nunca es devuelto por ninguna herramienta y nunca se escribe en el registro de auditoría (las llamadas REST se registran solo como método + ruta). Borrar token en el plugin elimina el archivo.

Alternativa sin interfaz/CI: establece la variable de entorno FIGMA_REST_TOKEN — anula el archivo.

Ámbito: por defecto, las llamadas REST apuntan al archivo actualmente abierto en Figma Desktop (el plugin envía su clave de archivo). Otros archivos requieren un parámetro fileKey explícito (clave simple o URL completa de Figma). Ten en cuenta que un PAT puede leer todos los archivos a los que su cuenta tiene acceso — mantén los ámbitos al mínimo.

El cliente REST es una lista blanca interna cerrada, no una puerta de escape HTTP genérica. Permite el estado del token, listas de versiones, contenido de documentos anclados a una versión, comentarios y metadatos de componentes publicados de todo el archivo. Una solicitud simple del archivo actual y todos los endpoints de nodo/CSS/exportación/variable/estilo/Recurso de desarrollo son rechazados antes de que se lea el token o se toque la red; esas operaciones deben usar los comandos locales de la API del Plugin mencionados anteriormente.

Modelo de seguridad

  • No se requiere token de la API de Figma — Figma se controla a través del plugin local, nunca de api.figma.com. El complemento REST es estrictamente opcional: sin un token, la ruta de código está inactiva, y con uno, el token reside en un archivo 0600 (o en tu propia variable de entorno), no en la configuración del cliente MCP.

  • Sin parches binarios — El modo Yolo/CDP se ha eliminado del motor integrado.

  • Comandos controlados por capacidadesfigma_run solo acepta Comandos expuestos por el Catálogo de Capacidades; connect no está expuesto, por lo que se aplica la conexión solo en Modo Seguro. El mismo plan resuelto impulsa la puerta de confirmación de escritura, el requisito de destino y la política de reintentos, evitando la deriva del adaptador.

  • Sin shell — el motor se inicia con execFile (shell:false).

  • Autenticación del demonio en dos capas, sin secreto en el cable — solicitudes HTTP firmadas (HMAC por solicitud sobre método/ruta/cuerpo, con clave del token de sesión, protección de repetición con nonce) + un apretón de manos mutuo de desafío-respuesta en el socket del plugin (lista blanca de Origin/Host). Ni el token de sesión ni la clave de acceso se transmiten nunca en ninguna dirección — consulta Apretón de manos.

  • Plugin bloqueado a localhostplugin/manifest.json restringe networkAccess.allowedDomains a ws://127.0.0.1:3456–3460.

  • Estado aislado — token, pid, clave y registro de auditoría viven bajo ~/.figma-bridge-mcp/, separados de cualquier instalación ascendente de figma-ds-cli.

  • Registro de auditoría — cada comando ejecutado se añade a ~/.figma-bridge-mcp/audit.log (con ids de nodo tocados, etiquetas opcionales y una entrada de finalización que registra éxito/fracaso — la fuente de datos para figma_history). Rota a los 5 MB; se mantiene una generación anterior (audit.log.1) que aún es leída por figma_history.

Puerto de reserva. El demonio enlaza el primer puerto libre en 3456–3460 y lo publica en ~/.figma-bridge-mcp/daemon-port; las capas CLI/MCP resuelven el puerto por llamada (env DAEMON_PORT > archivo de puerto > 3456), y el plugin escanea todo el rango, por lo que un proceso externo que ocupe el 3456 ya no bloquea la conexión. La comprobación del ocupante es una sonda /health no autenticada, y las solicitudes autenticadas están firmadas con HMAC — un ocupante en un puerto del rango no ve ni el token de sesión ni nada que pueda repetir (las firmas vinculan la marca de tiempo, el nonce, el método, la ruta y el cuerpo; el demonio rechaza los nonces reutilizados). El socket del plugin es seguro en cualquier puerto del rango por la misma razón: el apretón de manos siguiente no transporta ningún secreto y vincula el puerto en el que se ejecutó. Establecer DAEMON_PORT explícitamente deshabilita la reserva; los valores fuera de 3456–3460 no son compatibles — el manifiesto del plugin está impuesto por Figma y no puede alcanzarlos.

Apretón de manos

El socket del plugin ejecuta un desafío-respuesta mutuo (proto 2, engine/src/lib/plugin-handshake.js):

daemon → plugin   {type:'challenge', proto:2, nonce:<dNonce>, port:<bound>}
plugin → daemon   {type:'hello', proto:2, nonce:<pNonce>, version, proof}
daemon → plugin   {type:'hello-ack', proof, restTokenConfigured}

donde proof = HMAC-SHA256(clave de acceso, transcripción) sobre ambos nonces, el puerto vinculado y la versión del plugin — con etiquetas de rol distintas y orden de nonces por dirección, por lo que ninguna prueba puede repetirse como la otra. De ello se derivan tres propiedades:

  • La clave nunca cruza el cable. Un proceso que enlaza un puerto del rango antes que el demonio y registra todo el intercambio aprende un HMAC sobre nonces que nunca volverá a ver. Esto elimina el riesgo residual que documentaban versiones anteriores, donde la clave en bruto era el primer marco que enviaba el plugin.

  • El demonio también se demuestra a sí mismo. Antes del proto 2, el plugin confiaba en quien respondiera y ejecutaba cualquier eval que se le enviara — hacerse pasar por el demonio no requería ninguna clave. El panel ahora rechaza todo comando hasta que el acuse de recibo se verifica.

  • El puerto vinculado está dentro de la transcripción. Un ocupante en el 3456 que reenvía al demonio real en el 3457 hace que el plugin firme el 3456 mientras que el demonio verifica el 3457, por lo que el relé colapsa.

No hay reserva del proto-1. figma_connect actualiza los archivos del plugin instalado en cada ejecución, por lo que actualizar es: ejecuta figma_connect, luego cierra y vuelve a abrir la ventana del plugin — un panel obsoleto recibe un error con nombre que dice exactamente eso, en lugar de un apretón de manos silenciosamente más débil.

El panel lleva su propia implementación de SHA-256/HMAC: la interfaz de usuario del plugin es un iframe de origen nulo en un entorno aislado, donde la disponibilidad de WebCrypto no es nuestra responsabilidad garantizar, y una reserva silenciosa a algo más débil es el peor resultado para un apretón de manos de autenticación. tests/plugin-handshake.test.js ejecuta ese código enviado contra el crypto de Node para que las dos implementaciones no puedan desviarse.

Limitaciones conocidas

  • Figma Slides está en beta y deliberadamente acotado. Se admiten la inspección de cuadrículas, la creación/duplicación/movimiento/eliminación de diapositivas, el estado de omisión y las transiciones. Las notas del orador, las encuestas/inserciones interactivas, los controles del presentador y un flujo de trabajo completo de creación de contenido no lo están. Consulta la hoja de ruta de Slides para candidatos accionables frente a los límites de la API del Plugin.

  • Las acciones de red que no sean localhost son pocas y explícitas: api setup (clonación única de git del espejo de la documentación de la API del Plugin de Figma, para figma_reference; api gap mide en su lugar contra el paquete oficial instalado @figma/plugin-typings), la obtención del índice de Storybook de import/map storybook (la URL/directorio que proporciones), y — solo cuando optas por el complemento REST — llamadas a api.figma.com. Nada más habla con la red — las integraciones de iconify/unsplash/remove.bg/screenshot-url del upstream se eliminaron por completo; <Icon> en el JSX de figma_render se renderiza como un marcador de posición con nombre (los iconos reales salen del archivo de Figma a través de export assets).

  • Un transporte, sin restos de CDP. Cada comando llega a Figma de la misma forma: motor → demonio → eval del plugin. El cliente Chrome-DevTools del upstream, su viaje redondo de shell figma-use, el asistente de instalación de parches binarios y la dependencia figma-use han desaprecido (~5.600 líneas eliminadas), por lo que no hay una segunda ruta de código que pueda eludir el puente del plugin.

Desarrollo

npm run check:contracts       # static JavaScript seam + plugin contracts
npm run check:architecture-latency # warmed latency budget in an idle process
npm run measure:architecture  # context, payload and local latency baselines
npm test                      # all contracts and regression suites

El lenguaje de dominio actual vive en CONTEXT.md, las decisiones arquitectónicas aceptadas en docs/adr/, la cobertura de la API en docs/figma-plugin-api-coverage.md y las instrucciones de lanzamiento en docs/releasing.md. El índice de documentación pública es docs/README.md.

Evita ejecutar un figma-cli del upstream al mismo tiempo. El demonio ahora reserva dentro de 3456–3460 cuando el 3456 está ocupado, por lo que ambos pueden coexistir, pero el plugin escanea todo el rango y los dos demonios usan diferentes claves de acceso — a cuál llegue primero el plugin es un lanzamiento de moneda. Esta compilación aísla sus propios archivos de token/pid/puerto bajo ~/.figma-bridge-mcp/.

Licencia

figma-bridge-mcp se publica bajo la Licencia MIT. Se proporciona "tal cual", sin garantía; los términos exactos de garantía y responsabilidad están en la propia licencia. Los avisos de derechos de autor y licencias de terceros se conservan en NOTICE y engine/LICENSE.

Inspiración y atribución

Dos proyectos dieron forma a este, de diferentes maneras.

figma-cli (Sil Bormüller) es de donde proviene el directorio engine/: se integró en la v2.1.0 en julio de 2026 y ha divergido desde entonces — el transporte CDP y el instalador de parches binarios han desaparecido, el socket del plugin está autenticado, y la mayor parte de lo que hace el motor ahora se escribió aquí. Cuatro archivos permanecen byte-idénticos al upstream. La licencia MIT del upstream se conserva en su totalidad en engine/LICENSE, y NOTICE registra lo que cambió.

figma-console-mcp contribuyó con una idea más que con código: que un puente de Figma puede ser genuinamente local — un socket de plugin en la interfaz de bucle local, sin relé en la nube, sin binario parcheado. Nada de esto se deriva de su fuente; las superfices de la herramienta, el transporte y el plugin no están relacionados. Donde este proyecto se diferenca es que el socket también demuestra quién está al otro lado.

Identidad del plugin. Los manifiesos de desarrollo usan los ids alineados con el producto figma-bridge-mcp y figma-bridge-mcp-dev. Figma clavea clientStorage — donde vive la clave de acceso emparejada — en el id del plugin. Las instalaciones anteriores a la 0.5.0, por lo tanto, necesitan reimportar el manifieso y pegar su clave de acceso de Bridge existente una vez.

Install Server
A
license - permissive license
A
quality
B
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.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • The Figma MCP server brings Figma design context directly into your AI workflow.

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

View all MCP Connectors

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/KaiUweHella/figma-bridge-mcp'

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