
A promessa do docstring da minha ferramenta MCP não foi honrada pela API do GitHub.
Cada ferramenta no meu servidor developer-presence MCP tem uma docstring de uma linha, porque essa é a única documentação que um agente chamando a ferramenta vê — sem README, sem especificação OpenAPI, apenas a string que está sob o decorador @mcp.tool(). Já encontrei e corrigi bugs reais onde essa docstring se desviou do que o código realmente fazia. Este é diferente: a docstring e o código concordavam perfeitamente um com o outro. Ambos estavam errados sobre o que um terceiro sistema — a própria API REST do GitHub — realmente aceita.
A ferramenta em questão
@mcp.tool()
def list_repos(sort: str = "updated", limit: int = 10) -> list:
"""Lista repositórios públicos. sort: updated|stars|forks. limit: 1-100."""
repos = _gh(f"/users/{GITHUB_USERNAME}/repos?sort={sort}&per_page={min(limit, 100)}")
return [...]
sort é interpolado diretamente na string de consulta e enviado para GET /users/{username}/repos. Sem validação, sem mapeamento — qualquer string que o chamador passar é a string que o GitHub recebe. A docstring diz que updated|stars|forks são as três opções. O README repetiu a mesma afirmação em sua tabela de ferramentas. Eu escrevi ambas, ao mesmo tempo, claramente acreditando nisso.
O que o endpoint do GitHub realmente aceita
Eu verifiquei a própria referência da API REST do GitHub para "Listar repositórios de um usuário" em vez de confiar na memória ou no código que já estava concordando consigo mesmo. O enum do parâmetro sort para este endpoint específico é created, updated, pushed, full_name — nada mais. stars e forks são valores de ordenação reais, apenas não aqui; eles pertencem ao endpoint separado de pesquisa de repositórios (GET /search/repositories), que esta ferramenta não chama.
A API do GitHub não gera erro em um valor de consulta não reconhecido. Ela simplesmente ignora e volta à sua própria ordenação padrão. Portanto, list_repos(sort="stars") nunca iria falhar de forma barulhenta — iria silenciosamente retornar repositórios na ordem que o GitHub decidir usar, sem nada na resposta informando ao chamador que seu pedido de ordenação foi deixado de lado.
# o que a docstring promete
list_repos(sort="stars", limit=5) # "top 5 repositórios mais estrelados"
# o que o GitHub realmente faz com sort=stars em /users/{username}/repos
# -> ignora, usa seu próprio padrão, sem erro, sem aviso
Esse é um modo de falha pior do que uma falha. Uma falha informa imediatamente que algo está errado. Este retorna uma lista plausível de cinco repositórios, em alguma ordem, e cada sinal disponível para o chamador — a ferramenta teve sucesso, a forma está correta, nenhuma exceção — diz que o pedido foi honrado.
Por que nada pegou isso antes
Esta ferramenta existe desde a primeira versão do servidor. Nada nas verificações automatizadas deste repositório jamais pegaria isso, porque a falha não é uma exceção do Python ou uma resposta malformada — é uma incompatibilidade semântica entre o que uma docstring promete e o que o enum de parâmetros documentado de uma API externa realmente suporta. scripts/check_key_facts.py verifica se os arquivos referenciados existem. Nada verifica se as alegações de uma ferramenta sobre uma API de terceiros correspondem ao contrato real dessa API. E como eu não tinha tentado chamar esta ferramenta com sort="stars" recentemente — eu uso principalmente updated — não houve um momento em que a incompatibilidade surgiria como um resultado visivelmente errado em vez de um errado silencioso.
A correção
As opções honestas eram: restringir a docstring apenas aos valores que o GitHub realmente suporta, ou fazer stars/forks realmente funcionarem da maneira que a docstring sempre prometeu. Eu optei pela segunda — o fato de o GitHub não suportar uma ordenação do lado do servidor não significa que o recurso não precisa existir, apenas significa que a ordenação deve acontecer após a busca, não na string de consulta:
_REPO_API_SORTS = {"created", "updated", "pushed", "full_name"}
_REPO_CLIENT_SORT_KEYS = {"stars": "stargazers_count", "forks": "forks_count"}
@mcp.tool()
def list_repos(sort: str = "updated", limit: int = 10) -> list:
"""Lista repositórios públicos. sort: updated|created|pushed|full_name|stars|forks. limit: 1-100."""
api_sort = sort if sort in _REPO_API_SORTS else "updated"
fetch_limEmpresas brasileiras que utilizam APIs externas devem garantir que a documentação e a implementação estejam alinhadas para evitar falhas silenciosas. A falta de validação pode levar a resultados inesperados, impactando a confiança nas ferramentas. A solução proposta pode ser aplicada para melhorar a robustez das integrações.
Noticias relacionadas
Servidor MCP 1.1.0 da endoflife.ai: Exposição KEV, verificações SBOM e dispositivos de borda para agentes de IA
O servidor MCP da endoflife.ai agora possui dez ferramentas de leitura. Novas funcionalidades incluem exposição a vulnerabilidades conhecidas e status de dispositivos de borda, essenciais para a segurança de versões de software.

O que os agentes de IA realmente veem ao buscar seu Ator Apify
O artigo explora como os agentes de IA interagem com o servidor MCP da Apify, destacando a importância da descrição e otimização dos Ators para serem encontrados. Inclui uma análise de como os resultados de busca diferem entre humanos e agentes.
Como o Protocolo de Contexto do Modelo (MCP) muda para sempre o lançamento de recursos em SaaS
O Protocolo de Contexto do Modelo (MCP) é mais do que leitura de dados; sua aplicação mais poderosa é a orquestração de aplicativos em tempo de execução, permitindo que agentes de IA gerenciem anúncios e guias de onboarding sem código efêmero.
Gostou do conteudo?
Receba toda semana as principais novidades sobre WebMCP.