← Blog

Como construir um registry shadcn/ui que o Claude Code e o Cursor consigam usar de verdade

Um registry shadcn é metade do trabalho em 2026. Namespaces, docs em Markdown em URLs .md, llms.txt, um servidor MCP e registries privados, para que agentes de IA o instalem do jeito certo.

Preet Suthar · · 5 min de leitura

  • shadcn/ui
  • AI
  • React
  • Developer tools

A maioria dos componentes shadcn/ui hoje é instalada por um agente de código com IA, não por uma pessoa digitando o comando. Se você publica um registry, o agente é o seu usuário. Ele precisa encontrar seus componentes, ler as props sem adivinhar e rodar o comando de instalação certo. Um registry que só funciona para humanos clicando por um site de docs é um registry que acaba sendo mal usado.

Eu mantenho o HextaUI, um registry shadcn/ui, e passei boa parte deste ano fazendo-o funcionar com o Claude Code, o Cursor e o servidor MCP do shadcn. Isto é tudo o que acabou importando, na ordem em que eu faria de novo.

1. Publique um registry que passe na validação

Comece pelo básico. Cada item é um arquivo JSON que segue o schema do registry, com name, type, files, dependencies e registryDependencies. Coloque o índice em uma URL estável e cada item em uma URL previsível:

https://your-site.com/r/registry.json
https://your-site.com/r/button.json
https://your-site.com/r/all.json

Rode shadcn build para gerá-los a partir de um registry.json de origem, e valide antes de fazer o deploy. A CLI ganhou uma etapa de validação de registry em maio de 2026. Um registry que falha na validação falha em silêncio para os agentes, que então escrevem o componente à mão e erram.

Dois detalhes que fazem diferença de verdade:

  • registryDependencies com URLs completas. Quando o seu Dialog depende do seu Button, aponte para https://your-site.com/r/button.json, não para button, ou a CLI puxa o Button do shadcn/ui no lugar.
  • Um item all.json que depende de tudo. Agentes que recebem o pedido de "configurar o design system" vão procurar por ele.

2. Registre um namespace

Desde que o recurso de namespace de registry chegou, o usuário adiciona isto ao components.json:

{
  "registries": {
    "@hextaui": "https://hextaui.com/r/{name}.json"
  }
}

E depois instala com um nome curto:

npx shadcn@latest add @hextaui/dialog

Documente esse trecho na sua página de instalação e no seu llms.txt. A forma curta é o que o servidor MCP do shadcn usa na busca, então um registry sem namespace fica invisível para a única ferramenta que a maioria dos agentes usa para navegar por registries.

Se o registry for privado, a forma de objeto aceita headers com variáveis de ambiente que a CLI expande e nunca registra em log:

{
  "registries": {
    "@acme-pro": {
      "url": "https://acme.com/r/pro/{name}.json",
      "headers": {
        "Authorization": "Bearer ${ACME_TOKEN}"
      }
    }
  }
}

3. Dê a cada página de docs uma gêmea em Markdown

Agentes leem HTML mal. Leem Markdown bem. Faça toda URL de docs responder em .md com o mesmo conteúdo: descrição, comando de instalação, código-fonte completo, uso, exemplos, suporte a teclado e a tabela da API.

https://hextaui.com/docs/button      -> HTML for people
https://hextaui.com/docs/button.md   -> Markdown for agents

Não escreva o Markdown à mão. Gere-o a partir da mesma fonte da página, para que os dois nunca se desencontrem. No HextaUI a rota .md percorre a árvore React da página e a serializa, então adicionar um exemplo à página o adiciona ao Markdown de graça.

A referência da API é o que mais importa aqui. Um agente que consegue ler uma tabela de props não alucina um size="xl" que não existe.

4. Publique llms.txt e llms-full.txt

llms.txt é um índice em Markdown na raiz do seu site: o que o projeto é, quando usar, quando não usar, como instalar e uma linha por página de docs com o link .md dela. llms-full.txt é todas as páginas de docs concatenadas, para agentes que preferem carregar tudo de uma vez.

A seção "quando não usar" é a parte que as pessoas pulam e a parte que poupa tickets de suporte. Se o seu registry é só React e Tailwind, diga isso, ou um agente vai tentar instalá-lo em um projeto Vue.

Mantenha o comando de instalação nas dez primeiras linhas. Agentes leem o começo.

5. Rode um servidor MCP, somente leitura, sem chave

A CLI do shadcn tem o próprio servidor MCP (npx shadcn@latest mcp), que busca em qualquer registry do components.json. Isso cobre as instalações. Não cobre docs, mapas de teclado nem exemplos.

Por isso eu rodo um segundo em https://hextaui.com/mcp, Streamable HTTP, somente leitura, sem chave de API, com cinco ferramentas: search_docs, get_component, get_component_api, get_examples e get_install_command. O Claude Code se conecta com uma linha:

claude mcp add --transport http hextaui https://hextaui.com/mcp

O Cursor e o VS Code aceitam a mesma URL na configuração de MCP. Uma vez conectado, "adicione um combobox do HextaUI com resultados assíncronos" vira uma busca nas docs, uma leitura da API e o comando de instalação certo, sem chute no meio do caminho.

Torne-o descobrível também. Publique um server card em /.well-known/mcp/server-card.json e um server.json no formato do registry do MCP. Os agentes e as ferramentas ao redor deles estão começando a olhar ali primeiro.

6. Descreva a superfície HTTP com OpenAPI e erros de verdade

Tudo acima também é HTTP puro, e os agentes chamam HTTP diretamente cada vez mais. Publique um openapi.json com operation ids e respostas tipadas. Retorne os erros como application/problem+json da RFC 9457, com um campo resolution que diz o que fazer em seguida:

{
  "type": "https://hextaui.com/docs/api#not-found",
  "title": "Component not found",
  "status": 404,
  "detail": "No component named 'modal'.",
  "resolution": "Try 'dialog' or 'alert-dialog'. The catalog is at /mcp/index.json."
}

Um agente que recebe um 404 com uma dica se recupera. Um agente que recebe uma página de erro em HTML escreve o componente de memória.

7. Publique um arquivo de skill

O Claude Code e uma lista crescente de agentes leem arquivos SKILL.md que explicam como usar uma ferramenta. Coloque um em /.well-known/agent-skills/<name>/SKILL.md: como encontrar um componente, ler as docs dele e instalá-lo, com os comandos exatos. É uma página de Markdown e é a página de maior alavancagem do site.

8. Teste com os agentes, não com você mesmo

Abra um projeto Next.js novo no Claude Code com o seu servidor MCP conectado e nenhum outro contexto. Peça para "adicionar um date picker de <your registry> com intervalo e uma regra que desabilita fins de semana". Observe o que ele faz. Cada chute errado é uma lacuna nas suas docs em .md ou no seu llms.txt.

Depois faça o mesmo no Cursor só com o llms.txt e sem MCP. Depois com nada além da URL. O registry deve degradar com elegância nos três cenários.

O que isso te rende

Um agente com o servidor MCP ou as docs em .md conectados lê a tabela de props em vez de adivinhá-la, roda o comando de instalação em vez de reescrever o componente e instala as dependências na ordem certa. O lado de registry do HextaUI foi mais ou menos uma semana de trabalho. O lado dos agentes levou mais tempo, e é a parte que tornou o registry utilizável por quem hoje faz a maior parte das instalações.

Se quiser ver tudo isso funcionando: hextaui.com/llms.txt, qualquer página de docs com .md no final, as docs do MCP e as docs da API com a especificação OpenAPI.

FAQ

Preciso do meu próprio servidor MCP se a CLI do shadcn já tem um? O MCP do shadcn cobre busca e instalação nos registries listados em components.json. O seu servidor cobre docs, APIs e exemplos. A maioria dos registries se beneficia dos dois.

O servidor MCP deve exigir uma chave de API? Não para docs públicas. Cada chave que você exige é um agente que desiste. Reserve a autenticação para itens privados e use bearer tokens pelos headers do components.json.

Como gero a documentação em Markdown sem duplicar conteúdo? Renderize a mesma árvore de componentes que a página usa e serialize-a em Markdown. Uma fonte, dois formatos.

O que vai no llms.txt? Uma descrição, quando usar e quando não usar, o comando de instalação, o trecho do namespace e uma linha por página de docs apontando para o seu .md.