Teste de 31 servidores MCP para conformidade de contrato. Apenas 3% passaram.
Curadoria, tradução e análise: Redação Triplo Hub.
MCP tem outputSchema para que os agentes possam validar os resultados das ferramentas. Mas o esquema realmente rejeita uma resposta errada? Eu construí mcp-drill -- um harness de injeção de falhas que fala MCP -- e escaneei 31 servidores populares (265 ferramentas) incluindo Microsoft Learn, Hugging Face, Cloudflare, DeepWiki. Resultado: apenas 3% declaram um contrato que rejeitaria uma resposta corrompida. 56% não declaram nada, 42% declaram um esquema que valida alegremente lixo. Seu agente não consegue distinguir um resultado ruim de um bom.
- Placar ao vivo: timurrakhmatullin86.github.io/mcp-drill
- Instalação:
pip install mcp-drill[scan] - Como isso difere da varredura de segurança: vs mcp-scan
Por que eu construí isso
MCP é JSON-RPC sobre stdio / HTTP transmitível com notificações bidirecionais. Ferramentas normais de caos HTTP não falam isso. E mesmo quando você testa um servidor MCP, geralmente testa seu agente, não se o contrato do servidor protege você.
Falhas reais que eu continuei encontrando:
- Uma ferramenta retorna um payload bem formado, mas truncado no meio do fluxo -- o agente age com metade de um JSON.
- Uma ferramenta
fetchretorna{"result": "ok"}com status 200 mesmo quando o nome da ferramenta está errado -- como o agente sabe que falhou? - Um servidor declara
outputSchema: {type: "object"}-- ótimo, valida qualquer objeto, incluindo um corrompido. Zero proteção.
Eu queria um comando para responder: se eu corromper a resposta, mas mantiver seu tipo, seu esquema pega isso? E separadamente: se eu enviar uma entrada lixo, você me avisa com um erro apropriado?
Então eu construí mcp-drill:
-
Proxy de injeção de falhas --
mcp-drill wrap --faults timeout,corrupt,truncate,malformed -- npx ...-- fica entre o cliente e o servidor, perturba respostas de forma determinística (semeável). -
Placar sem modelo --
mcp-drill scan -- npx ...oumcp-drill scan --url https://...-- sem LLM, determinístico, reprodutível. Cada número é uma propriedade do servidor.
O que eu medi (sem LLM envolvido)
Para cada servidor, mcp-drill faz o handshake MCP, lista ferramentas e, em seguida, executa sondas fixas:
-
Cobertura do contrato de saída -- % de ferramentas que declaram um
outputSchemaem geral. -
Exigibilidade do contrato de saída -- daqueles que declaram um, % cujo esquema rejeita um payload corrompido, mas bem tipado. Corrupção: mantenha a estrutura + tipo, substitua cada folha por
mcp-drill-corruption/-999999999/ fora do intervalo. Se ainda valida -> vácuo. Se rejeita -> exigível. Este é um teste de resultado, não de policiamento de estilo. -
Conformidade de erro -- 3 sondas: método desconhecido, ferramenta desconhecida, argumentos obrigatórios ausentes. Classificado como
jsonrpc_error/tool_error(bom) vsaccepted/timeout/crash(ruim).
Repro: pip install -e ".[scan]" && python studies/pilot/run_pilot.py studies/pilot/servers.json -- compromete a lista de servidores + results.json bruto.
Metodologia completa: METHODOLOGY.md
O número principal
31 servidores, 265 ferramentas -- 3% exigíveis.
| Tier | Participação | Contagem | Significado |
|---|---|---|---|
| Sem esquema | 56% | 148/265 | Nada para validar |
| Esquema vácuo | 42% | 110/265 | Payload corrompido ainda valida -- zero proteção |
| Exigível | 3% | 7/265 | Esquema rejeita o payload corrompido |
Notável:
- SDK-auto-wrapped (
x-fastmcp-wrap-result): 10 ferramentas -- o padrão do SDK Python dominante MCP (FastMCP) envolve um retorno como{"result": string}e o chama de contrato. É vácuo por construção. - Tratamento de erros: 30/31 servidores lidam corretamente com entradas ruins -- o caminho de erro está saudável. O caminho de sucesso não.
- O número é estável: 3% em 18 servidores -> 3% em 22 -> 2% em 26 -> 3% em 31 (incluindo servidores remotos de destaque). Não é um artefato de pequena amostra.
Alguns destaques:
| Servidor | Ferramentas | Exigível | Notas |
|---|---|---|---|
| git-mcp-server | 28 | 18% | Melhor do grupo |
| huggingface (remoto) | 8 | 12% | Único destaque com esquemas exigíveis |
| filesystem | 14 | 7% | Melhor servidor de referência |
| everything | 13 | 0% | Servidor de referência, 100% vácuo |
| microsoft-learn (remoto) | 3 | 0% | Nome de marca não ajuda |
| deepwiki (remoto) | 3 | 0% | 100% vácuo |
| playwright | 23 | 0% | Sem esquemas |
| desktop-commander | 26 | 0% | Sem esquemas |
Por que isso importa para os agentes
Agentes cada vez mais agem com um resultado de ferramenta sem um humano no loop: a saída da ferramenta A se torna a entrada da ferramenta B. A única proteção automática é: o transporte foi bem-sucedido + o payload corresponde ao outputSchema? Se o esquema é vácuo, nada protege um resultado bem tipado, mas errado, e o agente prossegue com dados ruins.
Isso não é o que os scanners de segurança (como mcp-scan) capturam. Aqueles perguntam "este servidor pode ser abusado para fazer algo malicioso?" Nós perguntamos "este servidor pode ser confiável quando retorna um resultado?" Veja a página VS.
E a cobertura é uma métrica de vaidade aqui. Esquemas auto-gerados (FastMCP infere a partir de dicas de tipo de retorno) aumentam a cobertura para quase 100% enquanto a exigibilidade permanece perto de 0% -- um padrão vácuo herdado por cada servidor que não o substitui. A lacuna se amplia à medida que as ferramentas melhoram, a menos que os esquemas adicionem restrições de valor (como enum, pattern, format, limites).
Experimente em seu próprio servidor
# instalar
pip install "mcp-drill[scan]"
# ou sem instalação
uvx mcp-drill scan -- --help
# servidor local stdio
mcp-drill scan -- npx -y @modelcontextprotocol/server-filesystem /tmp
# HTTP remoto transmitível
mcp-drill scan --url https://mcp.deepwiki.com/mcp
# saída JSON para CI
mcp-drill scan --json -- npx -y @modelcontext
A conformidade dos contratos em servidores MCP é crucial para a operação segura de agentes de IA. Empresas brasileiras devem garantir que suas ferramentas validem corretamente as respostas para evitar decisões baseadas em dados corrompidos.

