Aseprite MCP Server
# Aseprite MCP Server
Servidor Model Context Protocol (MCP) de código aberto em TypeScript que conecta clientes de IA (como Google Gemini, Claude Desktop e outros clientes compatíveis com MCP) ao editor de pixel art Aseprite.
> [!NOTE]
> **Projeto Comunitário Não Oficial:** Este projeto é desenvolvido de forma independente pela comunidade e **não é afiliado, patrocinado ou endossado** pelos criadores do Aseprite (David Capello / Igara Studio S.A.).
O servidor permite inspecionar sprites, ler pixels, editar imagens, controlar camadas, frames e animações, validando cada alteração por meio de previews PNG gerados pelo motor do Aseprite. A comunicação com o Aseprite ocorre via WebSocket loopback local por meio de um script bridge em Lua, sem emulação de cliques de mouse e com políticas estritas de proteção de arquivos.
Fluxo principal:
```text
Observar -> analisar -> editar -> inspecionar novamente -> corrigir
```
---
## Recursos principais
- **Inspeção visual rica**: previews em PNG com escala nearest-neighbor, réguas de coordenadas e grades customizáveis.
- **Leitura precisa de pixels**: formatos hexadecimal (`#RRGGBBAA`), RGBA, indexado e compacto otimizado para economia de tokens.
- **Edição em lote e Undo atômico**: operações em lote agrupadas em uma única entrada de histórico de Undo.
- **95 ferramentas MCP tipadas**: pixels, formas, referências locais, arquivos, camadas/grupos, frames/tags, cels, slices, seleções, tilesets/tilemaps, preview animado, revisão visual e análise de pixel art.
- **Estrutura nativa do Aseprite**: cels vinculados, grupos aninhados, pivôs/nine-patch, blend modes, merge/flatten e exportação avançada por tag, intervalo e camada.
- **Ciclo visual incremental**: preview opcional após mutações, filmstrip, onion skin, comparação exata entre frames, checkpoints e histórico de alterações por revisão.
- **Qualidade de pixel art**: lint heurístico, CIEDE2000, análise de paleta, rampas com hue shift e dithering Bayer determinístico.
- **Segurança de arquivos**: contenção estrita de caminhos (`ASEPRITE_ALLOWED_PATHS`), política no-clobber por padrão (`overwrite: true` explícito) e validação de arquivo esperado no salvamento.
- **Bridge autenticável e versionado**: handshake obrigatório, sessão identificada, compatibilidade de protocolo verificada e token opcional (`ASEPRITE_BRIDGE_TOKEN`).
- **Superfície configurável**: modo somente leitura e seleção de toolsets para reduzir risco e custo de descoberta.
- **Mock Bridge em memória**: possibilita testes de integração rápidos e headless sem necessidade de abrir a interface do Aseprite.
- **Transporte padrão stdio**: mensagens de protocolo MCP isoladas em `stdout` e registros de diagnóstico em `stderr`.
---
## Arquitetura
```text
Cliente MCP (Gemini / Claude / outros)
|
| MCP sobre stdio
v
Aseprite MCP Server (Node.js/TypeScript; protocolo bridge 1.x)
|
| WebSocket JSON-RPC em 127.0.0.1:32123 (com auth opcional)
v
Bridge Lua (aseprite-bridge.lua)
|
v
Documento ativo no Aseprite
```
O servidor registra as ferramentas MCP, valida parâmetros de entrada e encaminha comandos em envelopes correlacionados por ID ao bridge Lua. Antes de aceitar comandos, servidor e bridge concluem um handshake `hello`/`hello_ack` com versão, sessão, capacidades e revisão. Uma sessão reconectada pode pedir ressincronização e consultar alterações estruturadas desde uma revisão conhecida.
---
## Requisitos
- **Node.js**: versão 18.0.0 ou superior.
- **npm**: gerenciador de pacotes incluso no Node.js.
- **Aseprite**: versão v1.2.30+ ou v1.3+ com suporte à API WebSocket em Lua.
- **PowerShell**: para execução dos scripts de conveniência no Windows.
---
## Instalação rápida
Clone o repositório e navegue até a pasta:
```bash
git clone https://github.com/Zythenth/MCP-Aseprite.git
cd MCP-Aseprite
```
### Windows (Automático)
No PowerShell:
```powershell
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\install.ps1
```
O script `install.ps1`:
1. Verifica Node.js >= 18 e npm;
2. Instala as dependências via `npm ci --ignore-scripts --no-audit --no-fund`;
3. Compila o projeto TypeScript gerando `dist/`;
4. Executa a suíte de testes (a menos que `-SkipTests` seja informado);
5. Verifica que servidor e bridge declaram a mesma versão de protocolo;
6. Copia `lua/aseprite-bridge.lua` para `%APPDATA%\Aseprite\scripts` caso o Aseprite seja detectado (ou se `-InstallLuaToAseprite` for fornecido) e confere o SHA-256 da cópia.
### Instalação manual (Todas as plataformas)
```bash
npm ci --ignore-scripts --no-audit --no-fund
npm run build
npm test
```
O ponto de entrada compilado será gerado em `dist/index.js`.
---
## Instalação do Bridge no Aseprite
Caso o script não tenha sido copiado automaticamente pelo instalador:
1. Abra o Aseprite;
2. Acesse o menu **File > Scripts > Open Scripts Folder**;
3. Copie o arquivo `lua/aseprite-bridge.lua` para dentro da pasta aberta;
4. No Aseprite, clique em **File > Scripts > Rescan Scripts Folder**;
5. Execute **File > Scripts > aseprite-bridge**.
O diálogo do bridge exibirá o estado da conexão (`Connecting...`, `Connected` ou `Disconnected (Reconnecting...)`). Ele tenta se conectar ao servidor em `127.0.0.1:PORT` e reconecta automaticamente.
> [!IMPORTANT]
> **Não edite o arquivo `lua/aseprite-bridge.lua` para alterar a porta.** A porta e o token de autenticação são lidos dinamicamente das variáveis de ambiente (`ASEPRITE_PORT` e `ASEPRITE_BRIDGE_TOKEN`). Como o Aseprite é um processo independente, configure essas variáveis no ambiente do sistema ou do usuário e reinicie o Aseprite.
---
## Configuração de Segurança e Ambiente
### 1. Política de Acesso a Arquivos (`ASEPRITE_ALLOWED_PATHS`)
Para impedir que comandos abram ou salvem arquivos fora das pastas do seu projeto, o servidor restringe operações de arquivo às raízes configuradas em `ASEPRITE_ALLOWED_PATHS`:
- **Formato**: lista de caminhos absolutos existentes separados por `;` no Windows ou `:` em ambientes POSIX.
- **Padrão**: caso a variável esteja ausente ou vazia, o servidor restringe o acesso ao diretório atual (`process.cwd()`), resolvido canonicamente via `realpath`.
- **Contenção e Symlinks**: links simbólicos que apontam para arquivos dentro das raízes permitidas são resolvidos e aceitos; links simbólicos que apontam para fora das raízes são bloqueados. Alvos de salvamento não podem ser symlinks existentes.
- **Extensões**: `.ase`, `.aseprite` e `.png` para leitura (`open_sprite`) e gravação (`save_sprite_as`); exclusivamente `.png` para `export_png`.
- **Proteção No-Clobber**: `save_sprite_as` e `export_png` nunca sobrescrevem arquivos existentes por padrão. Para sobrescrever intencionalmente, é necessário passar o parâmetro `overwrite: true`.
- **Salvamento Seguro (`save_sprite`)**: a ferramenta `save_sprite` não recebe caminho do usuário nem parâmetro de rota (é invocada sem argumentos). Ela opera diretamente sobre o arquivo já associado ao sprite ativo no Aseprite (`app.sprite.filename`). A validação de integridade `expectedFilePath` é realizada internamente pelo servidor MCP consultando `aseprite_status` antes de despachar o comando ao bridge Lua, que verifica a coincidência exata do caminho antes de executar o salvamento.
### 1.1. Raiz do projeto (`ASEPRITE_PROJECT_ROOT`)
`ASEPRITE_PROJECT_ROOT` define a base para caminhos relativos de referências, projetos e exports. Ela deve ser um diretório absoluto existente contido em uma das raízes de `ASEPRITE_ALLOWED_PATHS`; quando omitida, usa a primeira raiz autorizada.
- `references/heroi.png` é resolvido sob a raiz do projeto, nunca sob uma pasta arbitrária do computador.
- `find_reference_images` faz busca limitada por profundidade, quantidade de resultados e total de entradas; não percorre links simbólicos.
- `load_reference_image` aceita PNG, JPEG e WebP, valida tamanho e dimensões antes da decodificação e não altera o documento ativo.
- `save_project` grava somente `.aseprite`, preserva exatamente um nome fornecido e mantém no-clobber por padrão.
### 2. Autenticação por Token no WebSocket (`ASEPRITE_BRIDGE_TOKEN`)
Por padrão, o bridge conecta-se localmente em `127.0.0.1`. Para adicionar uma barreira extra contra acessos locais não autorizados de outros softwares rodando na máquina:
- **Formato**: token de 16 a 128 caracteres contendo apenas caracteres URL-safe ASCII (`[A-Za-z0-9._~-]`).
- **Geração**: gere um token seguro de 32 bytes aleatórios executando:
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
```
- **Configuração no Aseprite (Windows)**:
Como o Aseprite é executado separadamente, defina as variáveis no nível do usuário:
```powershell
[Environment]::SetEnvironmentVariable("ASEPRITE_PORT", "32123", "User")
[Environment]::SetEnvironmentVariable("ASEPRITE_BRIDGE_TOKEN", "seu-token-gerado", "User")
```
Após definir, reinicie o Aseprite e o cliente MCP para carregar as novas variáveis.
- **Validação e Privacidade**: a validação é feita em tempo constante (`crypto.timingSafeEqual`). O token **nunca** é impresso em logs, console, diálogos ou mensagens de erro. A interface do Aseprite exibe apenas `[Auth: enabled]` ou `[Auth: disabled]`.
- **Aviso**: conexões no loopback e tokens de autenticação mitigam conexões acidentais ou não autorizadas no host local, mas não eliminam todos os riscos em sistemas compartilhados. Se nenhum token for configurado, o servidor emitirá um aviso único na inicialização indicando que a autenticação no loopback está desabilitada.
O token não é colocado na URL. Ele é enviado somente no primeiro envelope de handshake. O servidor fixa o primeiro bridge autenticado e pronto como cliente ativo; conexões candidatas não substituem uma sessão ativa.
### 3. Modo somente leitura e toolsets
- `ASEPRITE_READ_ONLY=1` não registra ferramentas que alteram o sprite ou gravam arquivos. Inspeção, análise e abertura de documento permanecem disponíveis.
- `ASEPRITE_TOOLSETS` recebe uma lista separada por vírgulas. Valores aceitos: `core`, `visual`, `editing`, `files`, `shapes`, `layers`, `frames`, `palette`, `cels`, `slices`, `selection`, `tiles`, `animation`, `pixel-art` e `review`.
- `core` (`aseprite_status`) é sempre incluído. O valor ausente, vazio ou `all` ativa todos os conjuntos.
Exemplo enxuto para um agente revisor:
```powershell
.\start.ps1 -ReadOnly -Toolsets visual,palette,animation,pixel-art,review
```
### 4. Limites operacionais
O servidor limita payloads do bridge, comandos pendentes, dimensões de canvas, pixels por lote, frames de filmstrip/spritesheet, tamanho do checkpoint e cardinalidade da análise de paleta. Esses limites são proteções contra consumo acidental de memória/CPU; não constituem uma sandbox para processos locais já comprometidos.
---
## Configuração do Cliente MCP
### Exemplo Mínimo (Padrão)
No arquivo de configuração do seu cliente MCP (por exemplo, `gemini-mcp-config.json` ou configuração do Claude Desktop):
```json
{
"mcpServers": {
"aseprite": {
"command": "node",
"args": [
"C:/caminho/para/MCP-Aseprite/dist/index.js"
],
"env": {
"ASEPRITE_PORT": "32123",
"ASEPRITE_ALLOWED_PATHS": "C:/Projetos/PixelArt",
"ASEPRITE_PROJECT_ROOT": "C:/Projetos/PixelArt"
}
}
}
}
```
### Exemplo Endurecido (Com Token e Múltiplas Raízes)
> [!NOTE]
> O valor `"SubstituaPeloSeuTokenAleatorio12345"` abaixo é um marcador de posição demonstrativo com charset URL-safe válido (`[A-Za-z0-9._~-]`, entre 16 e 128 caracteres). Substitua-o pelo token seguro gerado no seu ambiente.
```json
{
"mcpServers": {
"aseprite": {
"command": "node",
"args": [
"C:/caminho/para/MCP-Aseprite/dist/index.js"
],
"env": {
"ASEPRITE_PORT": "32123",
"ASEPRITE_ALLOWED_PATHS": "C:/Projetos/PixelArt;D:/Assets/Sprites",
"ASEPRITE_PROJECT_ROOT": "C:/Projetos/PixelArt",
"ASEPRITE_BRIDGE_TOKEN": "SubstituaPeloSeuTokenAleatorio12345"
}
}
}
}
```
---
## Execução Manual e Scripts
Para executar o servidor manualmente:
```bash
npm start
```
No Windows via PowerShell:
```powershell
# Execução padrão
.\start.ps1
# Especificando porta, diretórios autorizados e a raiz para caminhos relativos
.\start.ps1 -Port 32123 -AllowedPaths @("C:\Projetos\PixelArt") -ProjectRoot "C:\Projetos\PixelArt"
# Execução com Mock Bridge (headless, sem Aseprite)
.\start.ps1 -Mock
# Revisão sem mutações, expondo apenas conjuntos necessários
.\start.ps1 -ReadOnly -Toolsets visual,palette,animation,pixel-art,review
```
> [!TIP]
> **Segurança de Segredos no Terminal:** Evite passar `-BridgeToken` como argumento de linha de comando para não gravar segredos no histórico do shell (`Get-History`, `.bash_history`) ou na listagem de processos do sistema. Prefira sempre definir a variável de ambiente `$env:ASEPRITE_BRIDGE_TOKEN` na sessão do terminal ou nas variáveis de ambiente de usuário antes de executar o script.
---
## Resumo das Ferramentas MCP
O conjunto completo contém **95 ferramentas únicas**. Para reduzir o contexto enviado ao modelo, exponha somente os toolsets necessários.
### Inspeção Visual e Leitura
- `aseprite_status`: Estado da conexão, arquivo ativo, tamanho do canvas, camada e frame selecionados e revisão atual.
- `get_sprite_info`: Estrutura hierárquica de camadas, frames, opacidades e blend modes.
- `inspect_sprite`: Preview PNG combinado com matriz de dados de pixels.
- `get_canvas`: Renderiza o canvas completo ou uma camada isolada como PNG.
- `get_pixel_grid`: Extração matricial de pixels (formatos hex, rgba ou compact).
- `get_pixel_grid_preview`: Visualização ampliada com réguas de coordenadas e grade de pixels.
### Edição de Pixels e Formas
- `set_pixels`: Aplicação de pixels em lote com Undo atômico.
- `set_pixel`: Aplicação de pixel único.
- `erase_pixels`: Limpeza de pixels para transparência (`#00000000`).
- `draw_line`, `draw_rectangle`, `draw_ellipse`: Rasterização de formas geométricas.
- `flood_fill`, `replace_color`: Preenchimento por tolerância e substituição de cores.
- `undo`, `redo`: Controle do histórico de edição.
### Camadas, grupos e composição
- Básico: `list_layers`, `create_layer`, `rename_layer`, `delete_layer`, `select_layer`, `set_layer_visibility`, `set_layer_opacity`, `move_layer`, `create_group`.
- Hierarquia: `list_layer_tree`, `move_layer_to_group`, `ungroup_layer`.
- Composição: `set_layer_blend_mode`, `merge_down_layer`, `flatten_layers`.
### Frames, tags e inspeção de animação
- Frames/tags: `list_frames`, `select_frame`, `create_frame`, `duplicate_frame`, `delete_frame`, `set_frame_duration`, `create_tag`, `list_tags`.
- Revisão: `get_onion_skin`, `get_filmstrip`, `compare_frames`, `inspect_animation`, `render_animation_preview`.
- `inspect_animation` combina frames, durações, tags, repetição, ordem efetiva de playback, camadas e cobertura de cels em uma resposta estruturada.
- `render_animation_preview` retorna primeiro um GIF reproduzível e depois um contact sheet PNG na mesma ordem temporal, com `previewId`, timing, FPS médio e revisão observada.
- Tags aceitam `forward`, `reverse`, `pingpong` e `pingpong_reverse`; `repeats: 0` representa loop contínuo.
### Cels, slices e seleções
- Cels: `get_cel`, `create_cel`, `delete_cel`, `set_cel_position`, `set_cel_opacity`, `link_cel`, `unlink_cel`.
- Slices: `list_slices`, `get_slice`, `create_slice`, `update_slice`, `delete_slice`, incluindo centro nine-patch e pivô.
- Seleção persistente: `get_selection`, `set_selection`, `clear_selection`, `invert_selection`. `set_selection` oferece substituição, união, subtração e interseção retangulares.
### Tilesets e tilemaps
- `list_tilesets`, `create_tileset`, `delete_tileset`, `get_tile`, `set_tile_pixels`.
- `create_tilemap_layer`, `get_tilemap`, `set_tiles`, incluindo índices e flags de espelhamento X/Y/diagonal.
### Pixel art, checkpoints e waivers
- `lint_pixel_art`: encontra indícios de pixels órfãos, outline interrompido, banding, pillow shading, drift de simetria e seams. Resultados são heurísticos e nunca corrigidos automaticamente.
- `analyze_palette`, `find_perceptual_palette_color`, `generate_palette_ramp`, `apply_ordered_dither`.
- `create_review_checkpoint`, `list_review_checkpoints`, `compare_review_checkpoint`, `delete_review_checkpoint`.
- `add_lint_waiver`, `list_lint_waivers`, `delete_lint_waiver`. Checkpoints e waivers são vinculados à sessão atual e mantidos apenas em memória.
### Arquivos e exportação
- `find_reference_images`: localiza PNG, JPEG e WebP por nome somente em diretórios autorizados, com busca recursiva limitada.
- `load_reference_image`: retorna a imagem de referência, dimensões, formato, transparência, hash e análise de paleta sem trocar o sprite ativo.
- `new_sprite`, `open_sprite`, `save_sprite`, `save_sprite_as`, `save_project`, `export_png`, `resize_canvas`.
- `export_sprite_sheet`: exporta por tag ou intervalo explícito, filtra camadas e organiza frames horizontalmente, verticalmente ou em grade, respeitando direção da tag, escala, espaçamento e no-clobber.
- `export_animation`: exporta a ordem efetiva de uma tag ou intervalo como GIF, spritesheet, sequência PNG ou PNG único. A sequência PNG usa nomes determinísticos e remove arquivos novos já escritos se uma execução no-clobber falhar parcialmente.
- APNG é rejeitado com mensagem explícita porque o bridge/Aseprite atual não oferece esse encoder; nenhum PNG estático é apresentado falsamente como APNG.
Ferramentas destrutivas exigem `confirm: true`; gravações em caminho existente exigem `overwrite: true`. Mutações com `returnPreview: true` retornam a imagem como conteúdo MCP sem repetir o base64 no bloco textual.
---
## Testes e integração contínua
- Testes unitários, de contrato, integração e E2E executados pelo Vitest; a configuração falha se uma seleção de testes não encontrar casos.
- O mock cobre o protocolo, recuperação incremental e as estruturas expostas pelas ferramentas.
- `test/real/aseprite-api-smoke.lua` valida contratos críticos dentro de um processo Aseprite real.
- O workflow de CI executa Node.js 18/20/22 e os sistemas Linux, Windows e macOS; um job separado compila a versão do Aseprite fixada no workflow e roda o smoke test real.
- O smoke local real depende de um executável Aseprite disponível; os testes headless do Node não substituem essa validação da API Lua.
---
## Solução de problemas
### O bridge permanece desconectado no Aseprite
1. Confirme que o servidor MCP está em execução.
2. Verifique se a porta coincide (`ASEPRITE_PORT`, padrão `32123`).
3. Se você configurou `ASEPRITE_BRIDGE_TOKEN` no servidor MCP, confirme que a mesma variável foi definida no ambiente do Aseprite e que o Aseprite foi reiniciado.
4. Tentativas com token divergente são rejeitadas com o código `1008 (Invalid bridge authentication)`.
### Erro de acesso negado em operações de arquivo
- Se receber `Access denied: path is outside allowed roots`, adicione o diretório do arquivo à variável `ASEPRITE_ALLOWED_PATHS`.
- Certifique-se de que os caminhos em `ASEPRITE_ALLOWED_PATHS` sejam absolutos e usem `;` como separador no Windows.
- Para usar caminhos relativos, defina `ASEPRITE_PROJECT_ROOT` dentro de uma das raízes autorizadas.
### Arquivo já existe e não é salvo
- Por padrão, o servidor adota a política no-clobber. Ao salvar em um arquivo existente via `save_sprite_as` ou exportar via `export_png`, inclua `"overwrite": true` nos argumentos da ferramenta.
---
## Licença
Distribuído sob a licença MIT. Consulte o arquivo [LICENSE](LICENSE) para obter mais informações.
TDQS
Scored across 43 tools
Several inspection tools overlap significantly: aseprite_status and get_sprite_info return nearly identical structural details, and get_canvas, inspect_sprite, and get_pixel_grid_preview all provide visual/pixel inspection with different granularity. Descriptions clarify 'primary' tools, but an agent still faces multiple plausible choices for common tasks like checking sprite state or viewing the canvas.
Names are consistently snake_case and mostly follow a verb_noun pattern (create_frame, list_layers, set_pixel). Minor deviations exist: new_sprite uses 'new' instead of the dominant 'create', aseprite_status is noun-first, and undo/redo are bare verbs.
43 tools is well above the typical 3-15 range and exceeds the 25+ threshold for 'too many' in this rubric. Although Aseprite is feature-rich, several tools are redundant (e.g., get_canvas vs inspect_sprite vs get_pixel_grid; aseprite_status vs get_sprite_info), making the set heavy for an agent to navigate.
Core painting, layer, frame, and file workflows are covered, but several resources lack full lifecycle operations. Tags only support create/list (no delete/rename/update range), palette lacks add/remove/resize operations, and frames have no reorder/move tool, creating notable dead ends for common animation tasks.