
Eliminando a taxa de configuração do 5-MCP com um pacote PyPI e Device Code Flow
Há algumas semanas, a integração de um novo usuário ao Codens parecia assim. Eles abriram .claude/settings.json e colaram cinco entradas de servidor MCP, uma para cada uma de nossas superfícies de produto. Em seguida, executaram cinco comandos de login separados. Cinco callbacks OAuth, cinco JWTs espalhados por arquivos de configuração, cinco chances de errar uma URL. Na primeira vez que conduzi alguém por isso em uma chamada, eles disseram muito educadamente "isso é muito". Eles estavam certos.
Nós lançamos codens-mcp para resolver isso. Um pacote PyPI, uma entrada MCP, um login. Trinta e um ferramentas através do Purple (o orquestrador), Red (auto-correção), Blue (QA E2E), Green (PRD) e Auth (SSO compartilhado e faturamento). E porque metade dos nossos usuários vive em caixas de desenvolvimento remotas onde o OAuth baseado em navegador é um problema, adicionamos um login com Fluxo de Código de Dispositivo que funciona via SSH, em contêineres e dentro do GitHub Codespaces. Este post é sobre as escolhas de design, incluindo aquelas sobre as quais ainda estou um pouco incerto.
Há um tipo particular de atrito em uma integração de cinco produtos que quero nomear antes de entrarmos na arquitetura. Não é o tempo. Os comandos de instalação reais levam talvez quatro minutos. É a desconfiança. Quando você é solicitado a colar cinco entradas em um arquivo de configuração que ainda não confia totalmente, cada passo faz você se perguntar se o produto vai valer a pena a configuração. Na terceira solicitação de login, metade dos usuários que observei desistiu de configurá-lo corretamente e apenas usou o Purple em isolamento. A perda de produto com isso não foi apenas alguns usuários. Foram os fluxos de trabalho entre produtos que nunca foram testados, porque ninguém nunca os viu funcionando.
Por que um pacote, e não cinco
Codens cresceu da mesma forma que a maioria dos sistemas multi-produto cresce: por acidente. O Purple foi o primeiro a ser lançado. Ele tinha 16 ferramentas MCP e uma CLI chamada purple-codens-mcp. As pessoas gostaram. Então o Red ganhou sua própria superfície MCP para relatórios de bugs e planos de correção. Depois o Blue para geração de testes. Depois o Green para consultas PRD. E então o Auth para inscrições e consultas de preços.
Cada um desses produtos tinha seu próprio backend, seu próprio JWT, sua própria entrada de servidor MCP. Do ponto de vista da organização do código, isso era aceitável. Do ponto de vista do usuário, era uma bagunça. As pessoas não querem instalar cinco pacotes do PyPI. Elas querem instalar uma coisa e obter todas as ferramentas.
Consideramos três abordagens:
A primeira foi: manter cinco pacotes, adicionar um meta-pacote que depende de todos eles. Gráfico de dependência limpo, mas os usuários ainda precisam de cinco entradas de servidor MCP porque cada pacote expõe seu próprio binário stdio. Isso não resolve nada.
A segunda foi: colapsar tudo em purple-codens-mcp e renomear o pacote depois. Tentador, mas purple-codens-mcp já tinha uma base de usuários fixando >=X.Y.Z em seus arquivos de bloqueio. Adicionar 15 novas ferramentas a esse pacote teria sido uma expansão de API furtiva e o nome estaria errado para sempre.
A terceira opção, que foi o que lançamos: um novo pacote chamado codens-mcp que reexporta as 16 ferramentas do Purple e registra as ferramentas Red/Blue/Green/Auth ao lado delas. O pacote vive em um diretório irmão (purple-codens/codens-mcp/) e declara purple-codens-mcp como uma dependência em tempo de execução. Usuários que já têm purple-codens-mcp em produção continuam funcionando. Novos usuários instalam uma coisa. O custo de empacotamento é uma dependência extra em pip list, que ninguém vai notar.
A coisa que eu gosto sobre esse layout é que mantém o código de autenticação em exatamente um lugar. A lógica de login vive em purple_codens_mcp.auth. O novo pacote importa esse módulo em vez de copiá-lo. Se uma futura migração do Auth Codens mudar o fluxo OAuth, eu conserto em um arquivo. A armadilha da duplicação é real e nós deliberadamente a evitamos.
Um benefício mais sutil da abordagem empacotada: as quatro superfícies de produto compartilham um auxiliar de credenciais. Cada ferramenta que chama Red, Blue ou Green o faz através de um acessor do tipo _red_client(api_url) que lê o mesmo arquivo de credenciais que o Purple usa. Não há estado de login por produto para reconciliar. Se um token for atualizado, todos veem o novo valor na próxima chamada. Mais cedo no design, eu tinha cada ferramenta de produto rastreando a autenticação de forma independente, e os casos extremos em torno de tokens expirados eram o tipo de coisa que eu debugava à meia-noite. Compartilhar um dicionário de credenciais fez esses bugs desaparecerem porque eles não podiam existir em primeiro lugar.
A ferramenta de registro entre produtos
Uma vez que todas as ferramentas estão em um pacote, você pode escrever ferramentas que abrangem produtos. A primeira que lançamos é codens_register_project_unified. Ela pega um repositório do GitHub e o registra através do Purple, Red, Blue e Green em uma única chamada.
Aqui está a tensão de design: Purple, Red, Blue e Green cada um tem seu próprio banco de dados e seu próprio endpoint /api/v1/projects. Não há commit em duas fases entre eles. Então, o que acontece quando você chama essa ferramenta e a API do Green está tendo uma má tarde?
A resposta transacional seria: reverter tudo, falhar de forma barulhenta. Mas "reverter" a criação de um projeto é irritante porque alguns desses backends disparam webhooks e notificações do Slack na criação, e reverter esses efeitos colaterais é bagunçado. Pior, um usuário que deseja tentar novamente não deve ser punido tendo que excluir três projetos meio criados manualmente.
Então, nós adotamos o melhor esforço. A ferramenta retorna um dicionário como este:
{
"purple_project_id": "prj_a1b2c3",
"red_project_id": "prj_d4e5f6",
"blue_project_id": None,
"green_project_id": "prj_g7h8i9",
"errors": [
{"product": "blue", "error_message": "503 Serviço Indisponível"}
]
}
Se três de quatro tiverem sucesso, você obtém três IDs e uma falha claramente rotulada para aquele que não teve. O usuário (ou o LLM que está controlando a ferramenta) pode reexecutar a chamada com products=["blue"] para tentar novamente apenas o que falhou. Esse parâmetro products tem como padrão todos os quatro, mas aceitar um subconjunto acaba sendo útil em duas outras situações: quando um cliente não paga por um dos produtos ainda, e quando um LLM está explorando e só quer registrar no Purple antes de se comprometer com o resto.
A honestidade do array errors é importante. Rascunhos anteriores da ferramenta tentaram ser inteligentes e agregar falhas em uma única string. Isso dificultou para um agente decidir programaticamente o que tentar novamente. A forma de lista de dicionários é mais feia em um logfile, mas trivialmente correta para analisar.
Ainda há um caso extremo que eu estou
A unificação de entradas de MCP pode facilitar a adoção de novas tecnologias por empresas brasileiras, reduzindo a complexidade na configuração de sistemas. Isso pode resultar em maior eficiência operacional e melhor aproveitamento das ferramentas disponíveis.

