Skip to main content
Glama
README.md
# figma-docs-mcp

Servidor MCP **local** que transforma a documentação/regras de negócio que vocês
mantêm no Figma em uma base pesquisável por **busca semântica**, exposta como uma
ferramenta para o Claude Code chamar sozinho quando tiver dúvida.

Fluxo: `reindex` puxa o texto dos arquivos da Figma via REST API → gera embeddings
locais → salva um índice em disco. O `server` carrega esse índice e expõe a tool
`buscar_documentacao`, que o agente usa para achar o trecho certo e o link direto
pro frame na Figma.

- **Roda local** (stdio), sem expor nada na rede.
- **Embeddings locais** (`multilingual-e5-small`): a doc nunca sai da máquina, sem API key, sem custo por token.
- **Atualização agendada** via cron rodando o `reindex`.

## Para a equipe — usar o índice pronto (não precisa de Figma)

Quem só vai **consultar** não precisa de token da Figma nem de rodar o plugin —
só do arquivo de índice (`data/index.json`), que **NÃO** vem no repositório (é
gerado e contém documentação interna). Pegue o `index.json` com quem mantém o
índice e:

```bash
git clone https://github.com/carlosfernandescrypt/figma-mcp.git
cd figma-mcp
npm install            # 1a busca baixa o modelo de embedding (~110MB), fica em cache
npm run build

# coloque o index.json recebido em data/index.json
mkdir -p data && cp /caminho/do/index.json data/index.json

# registra no Claude Code (escopo user = vale em qualquer projeto).
# $(pwd) resolve o caminho absoluto da sua cópia automaticamente:
claude mcp add figma-docs -s user \
  -e STORE_PATH="$(pwd)/data/index.json" \
  -- node "$(pwd)/dist/server.js"
```

Abra uma sessão nova do Claude Code e pergunte algo das docs — a IA chama a
`buscar_documentacao` sozinha. Quando o índice for atualizado, substitua o
`data/index.json` e reinicie a sessão.

> ⚠️ **Nunca** commite o `data/index.json` (docs internas) — o repositório é
> público. Ele já está no `.gitignore`; distribua o índice por canal interno.

## Pré-requisitos

- Node.js 20+ (testado com 22).
- Um **Personal Access Token** da Figma: Figma → Settings → Security → *Personal
  access tokens*. Permissão de leitura de conteúdo de arquivo é suficiente.

## Setup

```bash
npm install
cp .env.example .env
# edite o .env: cole o FIGMA_TOKEN e liste os arquivos a indexar
```

Para descobrir o **FILE_KEY** de um arquivo, olhe a URL dele:
`figma.com/design/<FILE_KEY>/Nome-do-arquivo`. Coloque as keys separadas por
vírgula em `FIGMA_FILE_KEYS`. Alternativamente, use `FIGMA_PROJECT_IDS` para
indexar todos os arquivos de um projeto de uma vez.

## Gerar o índice

```bash
npm run reindex
```

Na **primeira execução** o modelo de embedding (~110MB) é baixado e fica em cache.
As próximas rodadas são rápidas. O índice vai pra `./data/index.json`.

## Alternativa sem cota REST: extração por plugin (recomendado no plano Pro)

A API REST da Figma tem um **limite de custo** nos endpoints de leitura de arquivo
(`/files` e `/nodes`). Em planos **Pro**, esse orçamento é pequeno: indexar um
arquivo grande estoura a cota e a Figma devolve `429` com um `Retry-After` de
**dias** (`x-figma-rate-limit-type: low` + link de upgrade). Quando isso acontece,
o `reindex` não consegue puxar conteúdo até a cota resetar.

Solução que **não usa cota nenhuma**: extrair o texto por um **plugin que roda
dentro do Figma** (a API de plugin lê o documento localmente, sem REST).

1. Rode o Figma **desktop**. No Linux (sem app oficial) use o
   [IliyaBrook/figma-linux](https://github.com/IliyaBrook/figma-linux) (AppImage).
2. Abra o arquivo de docs. Menu **Plugins → Development → Import plugin from
   manifest…** e aponte pra `figma-plugin/manifest.json` deste repo.
3. Rode o plugin **Docs Extractor**. Ele varre páginas → frames → texto e gera
   `figma-chunks.json` (botão *Baixar* ou *Copiar JSON*).

   O plugin roda tanto em **modo design** (precisa de acesso de edição ao arquivo)
   quanto em **Dev Mode** (`editorType: ["figma","dev"]`). Em Dev Mode o Figma
   **impõe read-only** — plugins não conseguem editar o documento, só ler — então
   é o modo seguro pra arquivos de produção e funciona mesmo sem permissão de
   edição. O `code.js` chama `figma.loadAllPagesAsync()` pra varrer todas as
   páginas (em Dev Mode a Figma só carrega a página atual por padrão). **O plugin
   só lê: não há nenhuma chamada de escrita** — confira com
   `grep -nE "create|append|remove|delete|setPluginData" figma-plugin/code.js`.
4. Indexe esse dump localmente (sem token, sem REST):

```bash
npm run index:local /caminho/para/figma-chunks.json
```

Gera o mesmo `./data/index.json` que o `reindex`. A busca (`server`) funciona
igual. Dá pra rerodar quando quiser — sem nunca estourar cota.

## Ligar no Claude Code

Compile e registre o servidor (caminho **absoluto**):

```bash
npm run build
claude mcp add figma-docs -- node /caminho/absoluto/figma-docs-mcp/dist/server.js
```

Ou, sem build, rodando direto com tsx:

```bash
claude mcp add figma-docs -- npx -y tsx /caminho/absoluto/figma-docs-mcp/src/server.ts
```

O servidor lê o `.env` da própria pasta. Depois é só perguntar no Claude Code algo
como *"qual a regra de cálculo do frete?"* — ele chama a `buscar_documentacao`
sozinho. A descrição da tool e as instruções do servidor já orientam o agente a
consultar antes de assumir como uma regra funciona.

## Manter atualizado (cron)

Reindexa a cada 30 minutos (ajuste o intervalo conforme a frequência das mudanças):

```cron
*/30 * * * * cd /caminho/absoluto/figma-docs-mcp && /usr/bin/node dist/reindex.js >> reindex.log 2>&1
```

O servidor recarrega o índice ao iniciar; o índice em si é reescrito a cada
reindexação. Em uso pesado, reinicie o servidor após o reindex para recarregar
em memória (ou rode reindexações em horários de baixo uso).

## Limitações conhecidas (do design da opção 2)

- **Só texto.** Significado puramente visual (setas, agrupamentos, tabelas
  desenhadas) não é capturado. Cada chunk é o texto de um frame de primeiro nível.
- **Frames muito longos** são truncados pelo modelo (~512 tokens). Se a doc tiver
  frames gigantes, vale quebrá-los em seções menores na própria Figma.
- **Rate limits** da Figma: indexar muitos arquivos grandes leva tempo; por isso o
  índice é cacheado e não consultado ao vivo.

## Caminhos de evolução

- **Trocar pra embeddings de API** (ex.: OpenAI/Voyage): reescreva só `src/embeddings.ts`
  mantendo a assinatura `embed(texts, kind)`. Útil se quiser mais qualidade e não
  se importar com os dados saírem da máquina.
- **Vector store de verdade**: para dezenas de milhares de chunks, troque o
  `src/store.ts` por `sqlite-vec` ou `hnswlib-node`. O JSON + cosseno atual aguenta
  bem alguns milhares.
- **Webhooks** (`FILE_UPDATE`, requer plano pago): dispara o reindex só do arquivo
  que mudou, em vez do cron — índice sempre fresco e mais barato.
- **Servir pro time todo**: troque o `StdioServerTransport` por
  `StreamableHTTPServerTransport` e hospede como serviço, pra um índice único
  compartilhado.

## Estrutura

```
src/
  config.ts      # lê o .env
  figma.ts       # REST API da Figma + extração de texto em chunks
  embeddings.ts  # provedor de embedding local (e5 multilíngue)
  store.ts       # índice em JSON + busca por cosseno
  reindex.ts     # CLI: puxa via REST → chunka → embeda → salva (roda no cron)
  index-local.ts # CLI: indexa um dump JSON do plugin (sem REST, sem cota)
  server.ts      # servidor MCP stdio com a tool buscar_documentacao
figma-plugin/
  manifest.json  # plugin de dev pro Figma desktop
  code.js        # varre o documento e monta os chunks (API de plugin, sem REST)
  ui.html        # botões Baixar / Copiar o figma-chunks.json
```