Skip to main content
Glama
nerfaslol

Nerf (nib) MCP Server

by nerfaslol
README.md
# Nerf

Um canvas de diagramas — tipo Excalidraw ou tldraw — cujo estado é uma **API de primeira classe**. A ideia: um agente de IA desenha nele com a mesma fidelidade que a mão humana arrasta, via MCP, e os dois editam o mesmo quadro ao vivo.

> O canvas que o agente sabe usar.

`Nerf` é a identidade visual; o pacote, as variáveis de ambiente e o servidor MCP continuam usando o nome interno `nib`.

## Pré-requisitos

- **Node.js `^20.19.0` ou `>=22.12.0`** (o Vite 8 não roda em versões mais antigas). Confira com `node -v`.
- Um cliente MCP, se você quiser que um agente desenhe: **Claude Code** ou **Claude Desktop**.

## Rodar

```bash
npm install
npm run dev      # o canvas + a API /api/diagram no mesmo processo
```

Abra a URL que o Vite imprimir. É só isso — **não existe backend separado** para subir.

> **Usa Claude Code?** Abra a pasta e rode `/setup`: ele instala, valida o servidor MCP e roda os testes pra você.

| Comando | O que faz |
|---|---|
| `npm run dev` | Sobe o canvas. É o único jeito de rodar — a API é um plugin do Vite. |
| `npm run build` | Typecheck + build de produção. |
| `npm run lint` | oxlint. |
| `npm run mcp:test` | 20 verificações ponta a ponta do servidor MCP, contra um diagrama descartável. |

## Como funciona

O arquivo **`diagram.json`** na raiz é a fonte da verdade e o formato de fio do agente. O app faz `GET` a cada 1,5s e `POST` a cada mutação: qualquer coisa escrita nesse arquivo aparece no canvas em no máximo um segundo e meio, sem reload.

Ele **não vem no repositório** — nasce no seu primeiro traço (ou no primeiro `add_node` do agente) e fica fora do git, porque é o *seu* desenho, não código do produto.

Um plugin dentro do `vite.config.ts` serve `GET/POST /api/diagram` lendo e gravando esse arquivo, com escrita atômica (tmp + rename). O canvas usa o store **não controlado** do React Flow: pan, seleção, drag e resize ficam no estado interno da biblioteca, e a aplicação só consulta a instância nas fronteiras de carregar, salvar, desfazer e sincronizar.

## O MCP

`mcp/` é um servidor MCP (stdio, SDK oficial) que expõe o canvas como **18 tools** — `get_diagram`, `add_node`, `add_edge`, `batch_apply`, `layout_grid`, `color_nodes`, `delete_node`, `create_project`… A tabela completa está em [`mcp/README.md`](mcp/README.md).

O servidor **não depende do dev server**: as tools falam direto com o `diagram.json`. Você pode deixar o `npm run dev` aberto para ver o agente desenhando ao vivo, mas não é obrigatório.

### Ligar no Claude Code

Nada a fazer: o `.mcp.json` na raiz já registra o servidor. Ao abrir a pasta, o Claude Code pergunta se você confia nos servidores MCP do projeto — aceite, **reinicie o Claude Code**, e as tools `nib` aparecem. (Mudou o `.mcp.json`? Reiniciar é obrigatório; recarregar não basta.)

Confira com `/mcp` dentro da sessão, ou `claude mcp list` no terminal.

### Ligar no Claude Desktop

O Claude Desktop **não lê o `.mcp.json`** do projeto — ele tem um arquivo de configuração próprio, e o caminho precisa ser **absoluto**:

- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "nib": {
      "type": "stdio",
      "command": "node",
      "args": ["/caminho/absoluto/para/nib-release/mcp/nib-server.js"],
      "env": {}
    }
  }
}
```

Troque `/caminho/absoluto/para/nib-release` pelo lugar onde você clonou. No Windows, use barras duplas (`C:\\Users\\voce\\nib-release\\mcp\\nib-server.js`). Reinicie o Claude Desktop depois.

### Apontar para outro diagrama

`NIB_DIAGRAM_PATH` sobrescreve qual arquivo o canvas **e** o MCP usam. É assim que se testa sem escrever no seu desenho de verdade:

```bash
NIB_DIAGRAM_PATH=mcp/.test-diagram.json npm run dev
```

## As duas regras para não perder trabalho

O arquivo é *last-write-wins*: **sem lock, sem merge.** Quem escrever por último ganha. Por isso:

1. **Passe `expectedVersion`.** Se o humano mexeu no canvas nesse meio-tempo, a tool devolve `CONFLITO` em vez de apagar o trabalho dele. Sem isso, a escrita do agente some no próximo clique — ou apaga o clique.
2. **Prefira `batch_apply` a N chamadas.** Cada escrita separada é uma janela em que o outro lado pode te atropelar. Dez `add_node` são dez janelas; um `batch_apply` é uma.

Se você usa Claude Code, a skill em `.claude/skills/nib-canvas/` já ensina isso ao agente, e um hook impede que ele edite o `diagram.json` na mão em vez de usar as tools.

## Stack

React 19 · Vite · TypeScript · Tailwind v4 · shadcn (Base UI) · React Flow (`@xyflow/react`) · MCP SDK

## Licença

[MIT](LICENSE).