Generated output schema uses Pydantic's validation shape while structured output uses its serialization shape
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 52/100
Rechercherichtung
Beginne bei Tool.from_function in der Implementierung der MCP-Server-Tools, verwende die für die SDK-Versionen gezeigten Importpfade und verfolge, wie output_schema und structured_content erzeugt werden. Reproduziere die Beispiele alias_output und computed_output mit Draft202012Validator. Abgeschlossen ist die Aufgabe, wenn das generierte Schema beide serialisierten strukturierten Ergebnisse akzeptiert, einschließlich wireOut und doubled.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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
- Vorherrschende Sprache
- Python
- Sterne
- 24.3k
- Forks
- 4k
- Ø Merge
- 1 T. 11 Std.
- Gemergte PRs (30 T.)
- 30
Beitragsleitfaden
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus modelcontextprotocol/python-sdk
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
modelcontextprotocol/python-sdk#3566 ·
-
v1 v2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
modelcontextprotocol/python-sdk#3546 · 5 Kommentare ·
-
v1 v2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
modelcontextprotocol/python-sdk#3545 · 1 Kommentar ·
-
v1 v2
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 91/100
modelcontextprotocol/python-sdk#3508 · 2 Kommentare ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
modelcontextprotocol/python-sdk#3504 ·
Alle Issues in modelcontextprotocol/python-sdk
Ähnliche Issues
-
bug confirmed issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
open-webui/open-webui#30750 · 1 Kommentar ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
-
enhancement
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
OpenwaterHealth/openmotion-bloodflow-app#604 · 1 Kommentar ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
-
good first issue
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 90/100