Generated output schema uses Pydantic's validation shape while structured output uses its serialization shape

Aberta
#3,100 2 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
52/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Pouca atividade
Stack de tecnologia
python
Domínio
api, backend

Direção de pesquisa

Comece em Tool.from_function na implementação das ferramentas do servidor MCP, usando os caminhos de importação mostrados para as versões do SDK, e rastreie como output_schema e structured_content são produzidos. Reproduza os exemplos alias_output e computed_output com Draft202012Validator. A tarefa estará concluída quando o esquema gerado aceitar ambos os resultados estruturados serializados, incluindo wireOut e doubled.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

bug needs confirmation P2 v1 v2
Initial Checks
  • I confirm that I'm using the latest version of MCP Python SDK.
  • I confirm that I searched existing issues and pull requests before opening this issue.
Description

For a Pydantic return model whose validation and serialization shapes differ, the generated outputSchema describes the validation shape while structuredContent uses the serialization shape. The SDK therefore publishes an output schema that rejects its own generated structured result.

This is related to, but not a duplicate of, #1073 / #1099. That change aligned ordinary field aliases by serializing structured output with aliases. Split validation_alias / serialization_alias values still expose different validation and serialization shapes, and serialization-only fields such as computed_field reveal the same underlying mismatch.

Example Code
from __future__ import annotations

import asyncio
import json

from jsonschema import Draft202012Validator
from pydantic import BaseModel, ConfigDict, Field, computed_field

try:
    from mcp.server.mcpserver.tools.base import Tool
except ImportError:  # MCP Python SDK 1.x
    from mcp.server.fastmcp.tools.base import Tool


class AliasOutput(BaseModel):
    model_config = ConfigDict(extra="forbid", populate_by_name=True)
    value: int = Field(validation_alias="wireIn", serialization_alias="wireOut")


def alias_output() -> AliasOutput:
    return AliasOutput(value=1)


class ComputedOutput(BaseModel):
    model_config = ConfigDict(extra="forbid")
    value: int

    @computed_field
    @property
    def doubled(self) -> int:
        return self.value * 2


def computed_output() -> ComputedOutput:
    return ComputedOutput(value=1)


async def check(function: object) -> None:
    tool = Tool.from_function(function)
    converted = await tool.run({}, None, convert_result=True)
    structured = converted[1] if isinstance(converted, tuple) else converted.structured_content
    errors = [
        error.message
        for error in Draft202012Validator(tool.output_schema).iter_errors(structured)
    ]
    print(function.__name__)
    print("schema:", json.dumps(tool.output_schema, sort_keys=True))
    print("structured:", json.dumps(structured, sort_keys=True))
    print("schema_errors:", errors)


async def main() -> None:
    await check(alias_output)
    await check(computed_output)


asyncio.run(main())

Observed validator messages:

alias_output
schema: ... "wireIn" ...
structured: {"wireOut": 1}
schema_errors: ["Additional properties are not allowed ('wireOut' was unexpected)", "'wireIn' is a required property"]

computed_output
schema: ... "value" ...
structured: {"doubled": 2, "value": 1}
schema_errors: ["Additional properties are not allowed ('doubled' was unexpected)"]
Expected behavior

The generated outputSchema should describe the serialized structured output. Generating the output model schema in Pydantic serialization mode makes both witnesses conform: the alias schema uses wireOut, and the computed-field schema includes doubled.

Python & MCP Python SDK
  • Python: 3.13.13
  • MCP Python SDK: 1.28.1 (latest stable)
  • Also reproduced on current main: 2713b53b127afc094dc97d6067df9f69b647661c (2.0.0b2)
  • Pydantic: 2.13.4
Linguagem predominante
Python
Estrelas
24.3k
Forks
4k
Merge médio
1d 1h
PRs com merge (30d)
31

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de modelcontextprotocol/python-sdk

Todas as issues de modelcontextprotocol/python-sdk

Issues semelhantes

Mais issues de Python

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.