Voltar as noticias
O Schema do Meu Ferramenta MCP Lista nulo como Padrão para um Campo
MCP ProtocolMediaEN

O Schema do Meu Ferramenta MCP Lista nulo como Padrão para um Campo

Dev.to - MCP·17 de agosto de 2026

Eu procurei uma nova perspectiva em meu próprio servidor MCP esta semana, e continuei caindo nas mesmas funções que já endureci três ou quatro vezes — a proteção contra títulos duplicados, o portão de confirmação, a verificação de impressão digital. Todas correções reais, todas ainda funcionando. Mas cada uma delas dizia respeito ao que update_article faz uma vez que uma chamada chega até ele. Ninguém nunca olhou para a camada na frente disso: o que o FastMCP realmente transforma a assinatura da minha função Python, e se um chamador pode até mesmo fazer uma chamada legítima através dela.

update_article se parece com isso, reduzido à assinatura:

@mcp.tool()
def update_article(article_id: int, title: str = None, body_markdown: str = None,
                    published: bool = None, confirm: bool = False,
                    expected_fingerprint: str = None) -> dict:

A função inteira é construída em torno de None significando "não toque neste campo" — if title is not None: article["title"] = title, repetido para cada parâmetro opcional. Eu li essa função provavelmente uma dúzia de vezes enquanto corrigia o portão de confirmação, a verificação de obsolescência da impressão digital, a verificação de títulos duplicados. Nunca olhei para o que mcp.tool() faz com title: str = None antes que o corpo da função seja executado.

O FastMCP constrói seu esquema de ferramenta — e seu validador de argumentos em tempo de execução — a partir de um modelo pydantic que gera a partir das anotações de tipo da função, não a partir do que um humano lendo a assinatura inferiria. Eu verifiquei o que ele realmente produziu:

tools = await mcp.list_tools()
"title": {
  "default": null,
  "title": "Título",
  "type": "string"
}

Leia isso literalmente: o esquema diz que o padrão deste campo é null, e também diz que o único tipo aceitável é "string". Essas duas linhas se contradizem. type: str com um padrão None não é a mesma coisa que Optional[str] para pydantic — ele leva a anotação nua ao pé da letra e valida exatamente isso, independentemente de qual seja o padrão. O padrão só entra em ação quando a chave está ausente da chamada completamente.

Então eu tentei a coisa que o esquema em si implica que está tudo bem — enviando o padrão anunciado explicitamente:

await mcp.call_tool("update_article", {"article_id": 42, "title": None})
ToolError: Erro executando ferramenta update_article: 1 erro de validação para update_articleArguments
title
  Entrada deve ser uma string [type=string_type, input_value=None, input_type=NoneType]

Essa é uma chamada real de mcp.call_tool() através de uma instância real e instalada do FastMCP — não um stub, não uma hipótese. O pydantic a rejeita antes que o corpo de update_article, e seu design inteiro de if title is not None, seja executado. Apenas omitir a chave funciona. Eu verifiquei cada outro parâmetro implicitamente opcional neste servidor da mesma maneira: body_markdown, published, expected_fingerprint em update_article, e tags em create_article, todos cinco reproduzem isso, todos cinco pela mesma razão — uma anotação não-Optional nua com um padrão None.

Por que isso realmente importa, e não é apenas uma reclamação pedante do verificador de tipos: um cliente MCP preenchendo uma chamada de ferramenta não é um humano lendo a assinatura da função e sabendo para omitir chaves não utilizadas. Ele está construindo JSON a partir de um esquema, e o esquema que está lendo diz "default": null bem no campo. Um LLM decidindo que não quer mudar title nesta chamada tem duas maneiras igualmente razoáveis de expressar isso apenas a partir do esquema — deixar a chave de fora ou defini-la para o valor literal que o esquema mesmo acabou de dizer que era o padrão. Uma dessas duas leituras razoáveis falha. E quando falha, o que o chamador vê é um genérico ToolError do pydantic sobre string_type, não as mensagens de erro cuidadosamente escritas desta ferramenta — aquelas que passei três entradas de log de bug separadas para acertar para o portão de confirmação e a verificação de obsolescência nunca têm a chance de serem executadas.

A correção é um caractere de intenção por parâmetro,

Contexto Triplo Up

Empresas brasileiras que utilizam MCP devem estar atentas às definições de tipos em suas funções para evitar erros de validação. A correta implementação de schemas pode impactar diretamente na eficiência das chamadas de ferramentas. A compreensão dessas nuances é crucial para a integração de agentes de IA.

Noticias relacionadas

Gostou do conteudo?

Receba toda semana as principais novidades sobre WebMCP.