SPONSORED / REPO SPOTLIGHT

Por dentro de finestructure-ai/claude-plugin: um plugin do Claude Code em sete arquivos

O finestructure-ai/claude-plugin empacota a plataforma de aplicações Fine Structure como plugin do Claude Code e entrega /deploy, /fs-status e /fs-domain junto de um conector MCP hospedado que faz o trabalho de verdade. Vale a leitura menos pelo que ele publica e mais pelo que mostra sobre o formato de plugin: é tudo markdown e JSON, abaixo de quatorze kilobytes, sem etapa de build e sem saída compilada.

THE REPOSITORY

finestructure-ai/claude-pluginSponsored

Open finestructure-ai/claude-plugin

O repositório inteiro são sete arquivos

Clone o projeto e a árvore de arquivos cabe em uma tela:

.claude-plugin/
  plugin.json        686 B
  marketplace.json   507 B
commands/
  deploy.md          3.3 KB
  fs-domain.md       905 B
  fs-status.md       741 B
skills/
  fine-structure/
    SKILL.md         4.0 KB
LICENSE              MIT
README.md            2.3 KB

Sem package.json, sem lockfile, sem CI, sem dist. Nada é compilado nem empacotado, e não existe versão deste repositório cujo build possa falhar. Se você adiava escrever um plugin porque supunha haver uma cadeia de ferramentas, aqui está a correção: o formato é uma convenção de diretórios mais dois arquivos JSON, e o resto é prosa.

plugin.json é um ponteiro, não um programa

O manifesto carrega os campos de identidade de sempre (name, versão 0.1.0, description, author, homepage, repository, license, keywords) e depois um único bloco que faz todo o trabalho interessante:

"mcpServers": {
  "finestructure": {
    "type": "http",
    "url": "https://finestructure.ai/api/mcp"
  }
}

Duas chaves. Sem command, sem args, sem env. Compare isso com o formato que a maioria das configurações MCP assume: um processo local (npx, uvx, um caminho para um binário), uma lista de argumentos e um mapa env guardando uma chave de API. Declarar em vez disso um endpoint streamable HTTP tira o servidor da máquina do usuário, e por isso 105 ferramentas (o número que o arquivo de skill informa) ficam atrás de um manifesto de 686 bytes. Nada na versão de Node ou de Python do usuário consegue quebrar a instalação, e mudanças do lado do servidor entram no ar sem uma nova versão do plugin. O preço é a reprodutibilidade: não dá para fixar a superfície de ferramentas pelo lado do cliente.

marketplace.json transforma o repositório no próprio canal de distribuição

O Claude Code instala plugins a partir de marketplaces, e não de um registro de pacotes, e um marketplace é um arquivo JSON que lista plugins com um caminho de origem. O segundo arquivo em .claude-plugin faz exatamente isso, e sua única entrada de plugin traz "source": "./". O repositório é ao mesmo tempo o plugin e o marketplace que o serve, então publicar é um git push público:

/plugin marketplace add finestructure-ai/claude-plugin
/plugin install finestructure@finestructure

Os dois tokens idênticos na segunda linha são o nome do plugin no nome do marketplace, e eles colidem porque ambos se chamam finestructure. Se você copiar esse arranjo, dê nomes diferentes aos dois. As instruções de instalação ficam mais claras e sobra espaço para acrescentar um segundo plugin depois.

Comandos são modelos de prompt com frontmatter

Cada arquivo em commands/ é frontmatter YAML mais prosa. O deploy.md declara um description e um argument-hint, as duas cadeias que o usuário vê no seletor, e então estende uma árvore de decisão numerada: procurar na raiz do projeto um .finestructure.json com um app_id, caso contrário chamar list_apps e buscar correspondência de nome, caso contrário tratar como primeira publicação e usar $ARGUMENTS como nome da aplicação. O fs-status.md tem 741 bytes e faz o serviço de um subcomando de CLI: resolver a aplicação, chamar get_app_status, get_app_links e get_errors, resumir. O fs-domain.md percorre na ordem add_custom_domain, get_domain_verification, check_domain_verification, get_domain_ssl_status e set_primary_domain.

O ponto de projeto: nenhum desses arquivos chama coisa alguma. Eles nomeiam ferramentas, fixam uma ordem e descrevem o que fazer quando uma etapa falha. A execução acontece quando o modelo invoca ferramentas MCP. Um comando de barra é um prompt versionado, então revisá-lo não é perguntar se a lógica está correta, e sim se a instrução é ambígua.

As melhores linhas são as negativas. O deploy.md proíbe ferramentas de exclusão a menos que o usuário peça de forma explícita. O fs-domain.md observa que a propagação de DNS leva de minutos a horas e manda sugerir nova tentativa mais tarde em vez de entrar em laço de verificação. Isso é política de repetição e são grades de proteção escritas como frases, e é justamente o que os plugins ingênuos deixam de fora.

Skill contra command: puxar contra empurrar

O arquivo skills/fine-structure/SKILL.md tem dois campos de frontmatter, name e description, e a description se lê como condição de disparo, não como resumo: usar sempre que o usuário quiser publicar, criar ou atualizar uma aplicação, conectar um domínio, gerenciar dados ou segredos. Essa formulação é deliberada. Um comando dispara porque uma pessoa o digitou. Um skill dispara porque o modelo casou a descrição com o que está acontecendo.

A divisão de conteúdo decorre disso. O SKILL.md é um modelo mental, não uma lista de tarefas: o que é uma aplicação aqui (páginas JSX, componentes compartilhados, esquemas de entidades, nenhum código de servidor arbitrário), o que são entidades, quais operações gastam créditos. Depois os fluxos de trabalho como cadeias de ferramentas, de get_app_files para read_app_file, para write_app_file, para validate_app e para publish_app, com conjuntos de mudanças para edições em vários arquivos. Depois a semântica dos erros, que carrega o maior peso por byte: erros de autenticação significam reconectar, erros de crédito significam recarregar, e nenhum dos dois admite nova tentativa. Um agente sem esse conhecimento repete em laço uma falha que não deve ser repetida, e numa plataforma medida esse laço tem preço.

A regra para o seu próprio plugin sai limpa. Se um arquivo de comando está explicando o que é o seu produto, aquele parágrafo pertence ao skill. Comandos continuam sendo procedimentos.

OAuth é a razão de o manifesto não guardar segredos

O endpoint autentica por OAuth 2.1 com registro dinâmico de cliente, então a primeira chamada de ferramenta abre uma página de consentimento no navegador e o token vai parar no cofre de credenciais do Claude Code, não no repositório. Um fork é seguro por construção, a revogação é do lado do servidor e não uma edição de configuração que precisa alcançar cada máquina, e ninguém é convidado a colar uma chave de longa duração num arquivo que está a um commit descuidado de um diff público.

O que copiar para o seu plugin

Indicações concretas, mais ou menos na ordem de construção:

  • Comece com .claude-plugin/plugin.json contendo name, version e description. Todo o resto é opcional.
  • Se você mantém um endpoint MCP hospedado, declare "type": "http" com uma url em vez de um comando local. Isso apaga o ambiente de execução do usuário da sua superfície de suporte.
  • Entregue marketplace.json no mesmo repositório com "source": "./" enquanto houver um único plugin, e dê a ele um nome diferente do nome do plugin.
  • Dê a cada comando um description e um argument-hint no frontmatter, escritos como respostas às perguntas o que isso faz e o que eu digito depois.
  • Use $ARGUMENTS em vez de inventar sintaxe posicional. Não existe analisador, existe apenas substituição.
  • Escreva o corpo dos comandos como árvores de decisão com as ferramentas nomeadas de forma explícita. "Se o arquivo de configuração existir leia app_id, caso contrário chame list_apps" se sustenta melhor do que um parágrafo de intenções.
  • Coloque a semântica das falhas por escrito: quais erros são terminais, quais admitem nova tentativa e o que dizer em vez de tentar de novo.
  • Nomeie suas ferramentas destrutivas na prosa e proíba o uso delas sem pedido expresso.
  • Mantenha o modelo de domínio no SKILL.md e o procedimento no comando. Duplicação entre os dois é mau sinal.
  • Teste com /plugin marketplace add contra um caminho local ou contra o seu fork antes de apontar alguém para main.

Arestas

Três honestas, nenhuma fatal. Está tudo em inglês, e o formato não oferece gancho algum para corrigir isso: não há chave de locale no frontmatter, então localizar significa duplicar arquivos de comando ou aceitar o descompasso.

A história de não haver chaves de API tem um asterisco. O SKILL.md admite que as ferramentas de geração de mídia ficam fora da conexão OAuth e precisam de um token MCP estático com escopos de mídia, criado no Studio da plataforma e enviado em um cabeçalho bearer. O plugin lida bem com isso, mandando o modelo explicar a ausência em vez de repetir contra a parede, mas é um segundo caminho de autenticação parafusado num projeto cujo argumento de venda é ter apenas um.

E é a versão 0.1.0, sem changelog, sem testes e sem CI. Para markdown isso é defensável, embora uma verificação de esquema JSON em um hook de pre-commit pegasse a única classe de erro que de fato quebra instalações, um manifesto malformado. A submissão ao diretório está em análise no momento em que isto é escrito, então por ora a instalação é feita pela referência ao repositório.

Leia primeiro os três arquivos de comando, depois o SKILL.md, depois os dois arquivos JSON. Nessa ordem o formato se explica sozinho: o markdown decide o que deve acontecer e em que ordem, o servidor MCP decide o que de fato roda, e o manifesto é a costura fina entre os dois.

QUESTIONS

Asked about this repository

qual é a estrutura mínima de arquivos para um plugin do claude code?
Um arquivo: .claude-plugin/plugin.json com um name, uma version e uma description. Comandos, skills, agentes e hooks são camadas opcionais em cima. O finestructure-ai/claude-plugin é uma boa referência de tamanho porque usa várias dessas camadas e ainda assim soma sete arquivos e menos de quatorze kilobytes, sem etapa de build.
como funcionam os comandos de barra em um plugin do claude code?
Um comando de barra é um arquivo markdown em commands/ cujo nome de arquivo vira o nome do comando. O frontmatter fornece um description e um argument-hint para o seletor, e o corpo é um prompt que o modelo recebe quando o comando roda, com $ARGUMENTS substituído por tudo o que vier depois. O arquivo em si não executa nada, então o trabalho real precisa vir de ferramentas que o modelo possa chamar, e é por isso que este plugin combina comandos com um servidor MCP.
preciso de uma chave de API para usar um servidor MCP em um plugin do claude code?
Não, se o servidor falar OAuth. Este manifesto declara apenas "type": "http" e uma url, e o endpoint usa OAuth 2.1 com registro dinâmico de cliente, então a autorização acontece no navegador e o token fica no cofre de credenciais do Claude Code. A alternativa, um bloco env guardando uma chave, funciona, mas coloca um segredo de longa duração em um arquivo que os usuários copiam de um lado para outro. Uma ressalva visível aqui: as ferramentas de mídia ficam fora desse fluxo e ainda pedem um token estático.
como transformo um repositório do github em um marketplace de plugins do claude code?
Adicione .claude-plugin/marketplace.json com um name, um owner e um array plugins. Se ele servir um plugin do mesmo repositório, defina o source desse plugin como "./", que é o que este repositório faz. Os usuários então rodam /plugin marketplace add owner/repo seguido de /plugin install plugin-name@marketplace-name. Não há registro nem etapa de publicação entre um git push e um plugin instalável.

THE SPONSOR

The platform behind the endpoint

Fine Structure runs the hosted MCP server this plugin points at, and sponsors this publication.

finestructure.ai