Communitygithub.com

zeke/paper-app-skill

Trabalhe no aplicativo de design Paper (paper.design) por meio de seu servidor MCP local (as ferramentas mcp__paper). Use quando solicitado a projetar, criar protótipos ou explorar variantes no Paper, editar pranchetas ou slides em uma tela do Paper, capturar screenshots ou exportar PNGs, PDFs ou vídeos do Paper, mover ou clonar arquivos do Paper, usar fontes personalizadas ou imagens locais no Paper, ou transformar um design do Paper em código. Abrange peculiaridades do codemode, análise de resultados, exportação e soluções alternativas para screenshots, organização da tela e o que o MCP não pode fazer.

O que é paper-app-skill?

Esta skill capacita agentes de IA a interagirem com o aplicativo de design Paper por meio de seu servidor MCP local. Ela é essencial para desenvolvedores e designers que desejam automatizar tarefas de design, como criar e modificar pranchetas, escrever HTML diretamente na tela, exportar assets em vários formatos (PNG, PDF, MP4) e converter designs em código. A skill fornece orientações detalhadas sobre como chamar as ferramentas MCP do Paper corretamente, evitando armadilhas comuns como chamadas paralelas que falham, análise de resultados e uso de helpers reutilizáveis. Ela cobre fluxos de trabalho completos, desde a configuração inicial e verificação da conexão com o servidor até técnicas avançadas como organização de tela em grade, uso de fontes personalizadas com verificação de licença e criação de variantes de design. Também documenta claramente as limitações do que o MCP pode fazer, como não poder compartilhar arquivos ou mover nós entre documentos.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/zeke/paper-app-skill/tree/HEAD/skills/paper-app

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Prévia

Do README da skill

paper-app-skill preview

Documentação

Paper app

Paper é uma ferramenta de design cuja tela é HTML e CSS reais. O aplicativo de desktop Paper executa um servidor MCP local que permite que agentes leiam a tela e escrevam HTML nela como nós de design.

O servidor vem com seu próprio guia. Esta skill cobre o que esse guia omite: coisas aprendidas da maneira mais difícil ao longo de sessões reais.

Antes de começar

  1. Verifique se as ferramentas existem: await describeNamespace("mcp__paper") no codemode. Se o namespace estiver vazio ou ALL_TOOLS não tiver entradas mcp__paper__*, a sessão não se conectou, geralmente porque o Paper não estava aberto quando a sessão começou. O servidor está em http://127.0.0.1:29979/mcp e só responde enquanto o Paper estiver aberto. pi mcp list (execute no bash) mostra se o servidor em si está saudável. Se estiver, a sessão não pode se reconectar sozinha: peça ao usuário para executar /mcp reconnect paper no pi, ou /reload se isso não funcionar.
  2. Carregue o guia oficial uma vez por sessão: get_guide({ topic: "paper-mcp-instructions" }). Siga-o: publique um briefing de design antes de novos designs, escreva um grupo visual por chamada write_html, revise com screenshots e chame finish_working_on_nodes quando terminar. Outros tópicos: mobile-status-bar, figma-import, image-generation.
  3. Encontre o arquivo. list_resources({ limit: 200 }) lista arquivos sem que um esteja aberto. Passe fileId para toda chamada com escopo de arquivo. get_basic_info({ fileId }) funciona em um arquivo que não é a aba em primeiro plano, então raramente você precisa de open_file, que abre uma aba no aplicativo do usuário.
  4. Se o projeto tiver um AGENTS.md, procure o ID do arquivo Paper e as convenções de tela lá antes de explorar.

Chamando o Paper a partir do codemode

  • Execute chamadas dependentes do Paper em um único script com await, ou em turnos sequenciais. Nunca as emita como chamadas de ferramenta paralelas no mesmo turno. Chamadas paralelas causaram a maioria das falhas em sessões passadas, e cada uma foi mal interpretada como um bug do Paper: "Node not found" para um nó que uma chamada irmã acabara de criar, filhos chegando em ordem embaralhada, exportações perdendo escritas recentes e read falhando com ENOENT em uma exportação que ainda não havia sido escrita.
  • Toda ferramenta com escopo de arquivo requer fileId em sua declaração codemode, mesmo que as instruções do servidor digam que você pode omiti-lo. Omiti-lo falha na validação. Apenas get_basic_info e get_selection aceitam nenhum fileId.
  • Execute describeTool("mcp__paper__<name>") antes do primeiro uso de uma ferramenta. As formas dos argumentos não são adivinháveis: get_font_family_info recebe familyNames: string[], set_text_content e update_styles recebem um array updates, e export recebe um mapa nodes.
  • Ferramentas com escopo de arquivo retornam uma string simples: um bloco JSON de cabeçalho { file, contentHash }, depois o corpo. Ferramentas sem arquivo (list_resources, create_file, open_file, get_guide) retornam { content: [{ type: "text", text }] }. Não use regex para extrair o primeiro "id" de um resultado: é o ID do arquivo, e passá-lo como ID de nó falha com "Node not found".
  • Falhas com escopo de arquivo e erros de validação lançam exceções. Algumas falhas sem arquivo (como "Open a Paper file to use this tool.") resolvem com isError: true em vez disso. Não envolva chamadas do Paper em .catch(() => {}): uma forma de argumento errada então falha silenciosamente e a edição simplesmente nunca aparece.
  • "Your Paper file is currently disconnected from the server" significa que as escritas falham enquanto as leituras ainda funcionam. Dormir e repetir não resolveu em sessões passadas. Peça ao usuário para trazer o arquivo Paper de volta ao primeiro plano e repita.
  • get_screenshot não retorna imagem no codemode: seu resultado é achatado para a string de cabeçalho. Use o helper shot() abaixo, que exporta um PNG e o lê no mesmo script. Quando um harness chama ferramentas MCP diretamente em vez de através do codemode, as imagens de get_screenshot vêm.

Formas úteis de resultado, após analisar o corpo:

FerramentaCorpo
create_artboard{ id, name, worldX, worldY, width, height }
write_html{ createdNodes: [{ id, name, component }] }, apenas nós de nível superior
get_tree_summary{ summary }, uma árvore de texto indentada com Type "name" (id) W×H
get_children{ children: [{ id, name, component, childCount, x, y }], count }
find_nodes{ nodes: [{ id, name, component, matched: [{ styleName, styleValue }] }] }
duplicate_nodes{ duplicatedNodes: [{ sourceId, newId, descendantIdMap }] }
export{ exports: [{ nodeId, filePath }] }
update_stylesLista ignoredStyles quando um estilo é inerte naquele contexto. Verifique-o.

Helpers

Cole estes no topo de um script codemode, ou armazene-os uma vez e eval eles em chamadas posteriores:

var F = "<fileId>";
var txt = r => typeof r === "string" ? r : (r?.content ?? []).map(c => c.text ?? "").join("\n");
// Remove o cabeçalho { file, contentHash } que ferramentas com escopo de arquivo prefixam.
var body = r => { const t = txt(r); const i = t.indexOf("\n}\
"); return t.startsWith('{\n  "file"') && i > -1 ? t.slice(i + 3) : t; };
var json = r => JSON.parse(body(r));
var w = async (target, html, mode = "insert-children") =>
  json(await tools.mcp__paper__write_html({ fileId: F, targetNodeId: target, mode, html })).createdNodes;
// Exporta um nó para PNG, mostra-o e então exclui o arquivo de ~/Downloads.
var shot = async (id, scale = "1x") => {
  const { exports } = json(await tools.mcp__paper__export({ fileId: F, nodes: { [id]: [{ format: "png", scale }] } }));
  const p = exports[0].filePath;
  image(await tools.read({ path: p, offset: null, limit: null }));
  await tools.bash({ command: `rm -f "${p}"`, timeout: 5 });
};

Para reutilizar helpers entre chamadas: store("paper", helperSource), depois eval(load("paper")) no topo de cada script posterior. Declare helpers com var, porque const e let dentro de eval não vazam para fora. store() só mantém valores quando o script é bem-sucedido, então armazene helpers em um script que não faz mais nada.

Screenshots e exportações

  • Tire screenshots em uma chamada codemode separada das edições. Uma exportação no mesmo script das escritas pode ser executada antes que o Paper as renderize, então o PNG mostra conteúdo ausente ou desatualizado.
  • export escreve em ~/Downloads/<nome da prancheta>.png, com @2x ou @0.5x para outras escalas e sufixos (1), (2) quando um arquivo com esse nome já existe. Caracteres como ? e : tornam-se _. Sempre use o filePath retornado. Não selecione arquivos com ls -t ~/Downloads ou globs de nome: isso já pegou exportações desatualizadas de execuções anteriores.
  • Mova ou exclua exportações após lê-las para que não se acumulem em ~/Downloads. Deixe arquivos que você não criou em paz.
  • Use 0.5x para screenshots de revisão para economizar tokens, 2x para entregáveis (pranchetas 1920×1080 tornam-se 3840×2160).
  • export_combined_pdf mescla pranchetas em um único PDF, ordenado por posição na tela. export também faz vídeo mp4/webm, mais svg para nós SVG, jpg, webp, avif e pdf.
  • Para transformar pranchetas em Google Slides, veja references/slides-export.md.

Escrevendo HTML

A descrição da ferramenta write_html lista as regras (estilos inline, flex, sem margin, sem display: grid, sem tabelas, layer-name para nomes de camadas). Descobertas adicionais:

  • Uma <div> vazia se torna um nó Rectangle, mesmo com display: flex, e Rectangles não podem ter filhos. Escrever dentro de um falha com "cannot have children". Escreva um contêiner junto com seu primeiro filho, ou substitua o Rectangle com write_html no modo replace.
  • Texto rico não é suportado. Para código com destaque de sintaxe ou uma frase com uma palavra colorida, construa uma linha flex de nós de texto separados, um por token, cada um com white-space: pre. O código se torna uma linha por linha de código. Gere o HTML com um helper em vez de escrevê-lo manualmente.
  • Um background com camadas de gradiente ignora backgroundColor. Adicione a cor base como a última camada: linear-gradient(#F6F7F9, #F6F7F9).
  • <svg> inline funciona para ícones, logotipos e linhas de conexão, e aceita cores fill/stroke e variáveis de token. Coloque o SVG de um logotipo de marca inline em vez de vinculá-lo.
  • Preenchimentos de caminho SVG são invisíveis para find_nodes e get_computed_styles (que retorna {} para eles). Encontre os nós SVGVisualElement "Path" em get_tree_summary e recolorir-os com update_styles({ styles: { fill } }), que funciona.
  • Imagens locais precisam de um caminho absoluto com o esquema paper-asset://: <img src="paper-asset:///private/tmp/spec/foo.png">.
  • Colunas de largura igual em uma linha flex precisam de flex: 1; flex-basis: 0. Padding em uma coluna caso contrário a torna mais larga que suas irmãs.
  • Se o conteúdo cortar, defina a prancheta para height: "fit-content" com update_styles em vez de adivinhar uma nova altura.

Fontes

  • get_font_family_info({ fileId, familyNames: [...] }) verifica fontes instaladas na máquina e Google Fonts. Chame-o antes do primeiro estilo tipográfico em uma sessão.
  • Fontes instaladas no meio da sessão (por exemplo, em ~/Library/Fonts no macOS) não aparecem até que o Paper seja reiniciado. Peça ao usuário para sair e reabrir o Paper. Não o mate você mesmo, pois isso pode perder o estado deles.
  • Verifique a licença de uma fonte antes de colocá-la em um site público. Muitas fontes do dafont.com são gratuitas apenas para uso pessoal.
  • Para comparar muitas fontes sem reiniciar o Paper, renderize espécimes em PNGs transparentes localmente (por exemplo, com Pillow), coloque-os como imagens paper-asset:// em uma prancheta de espécime e instale apenas os finalistas.

Organizando a tela

  • Ao iterar em um design, duplique a prancheta e altere a cópia. Não edite pranchetas anteriores no lugar: os usuários querem ver a progressão e frequentemente pedem para voltar a uma versão anterior. Um usuário teve que pedir isso duas vezes em uma sessão.
  • create_artboard e duplicate_nodes colocam novas pranchetas no melhor espaço vazio, o que as espalha. Para organizá-las, defina top e left nas pranchetas com update_styles. Mantenha pelo menos 80px entre pranchetas.
  • Mantenha as explorações de design separadas da direção escolhida: em sua própria região da tela, ou em sua própria página (create_page, depois passe pageId). Você não pode alternar qual página o usuário está visualizando.
  • Para decks e conjuntos de variantes, use uma grade fixa (por exemplo, quatro por linha, x = x0 + col × (width + gap)). Quando uma prancheta é adicionada ou removida, reorganize o resto para que não haja lacunas e renumerar seus nomes.
  • Para variantes claras e escuras, coloque a linha clara no topo e a versão escura correspondente diretamente abaixo de cada uma. Para fazer as versões escuras, veja references/dark-mode-variants.md.
  • Dê às pranchetas nomes descritivos como Homepage · A (Editorial) ou 04 · What are Workers?. Os nomes dos arquivos exportados vêm deles.
  • IDs de nós não sobrevivem à sessão. Escreva o ID do arquivo, URL, esquema de nomenclatura, fórmula de grade e regras de estilo no AGENTS.md do projeto para que a próxima sessão possa retomar.

Design para código

  • Leia valores exatos com get_jsx (format: "inline-styles" ou "tailwind") e get_computed_styles. Nunca meça tamanhos ou cores de um screenshot.
  • Cores computadas podem vir como oklab(...). Copie-as literalmente em vez de convertê-las.
  • Após construir a página, compare-a em um navegador real com uma exportação do Paper, nos modos claro e escuro.

O que o MCP não pode fazer

  • Compartilhar arquivos ou gerenciar permissões. O usuário compartilha do aplicativo Paper: convide pessoas para a equipe para permitir que editem, ou envie a URL do arquivo para acesso somente leitura.
  • Mover arquivos para pastas. Novos arquivos de create_file caem fora das pastas do usuário, e o usuário tem que arrastá-los para dentro.
  • Mover nós entre arquivos. move_nodes só move dentro de um arquivo, entre páginas. Para mover o conteúdo de um arquivo inteiro, create_file({ cloneFileId, name }), verifique se as contagens de nós e pranchetas correspondem, depois delete_nodes os originais. Confirme com o usuário antes de excluir.
  • Alternar a página que o usuário está visualizando.

Habilidades Relacionadas