Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

func_metadata raises uncaught PydanticSchemaGenerationError for Iterator/AsyncIterator tool return annotations instead of the unstructured fallback

Aperta Adatta ai principianti
#3,573 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
65/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
api, backend

Direzione di ricerca

Il problema si trova in src/mcp/server/mcpserver/utilities/func_metadata.py. Guarda la riga 444 dove _create_output_model viene chiamato al di fuori del blocco try/except. La correzione consiste nello spostare quella chiamata all'interno del blocco try/except esistente che cattura PydanticUserError e pydantic_core.SchemaError. Testa con lo script di riproduzione fornito per assicurarti che i tipi di ritorno Iterator/AsyncIterator ora o ricadano su un output non strutturato o sollevino InvalidSignature come documentato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

v1 v2
Initial Checks
Release line

2.x (current stable)

Description

Registering a tool whose function is annotated -> Iterator[...] or -> AsyncIterator[...] — the PEP 484 spelling for generator functions — raises a raw pydantic.errors.PydanticSchemaGenerationError at registration time, instead of either falling back to an unstructured tool (structured_output=None, the default) or raising the SDK's InvalidSignature (structured_output=True). The same happens via @server.tool() / Tool.from_function(), so a properly typed generator tool cannot be registered at all.

Actual output of the script in "Example Code" (error text truncated at 80 chars by the script):

func_metadata(search): UNCAUGHT pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for typing.Iterator[str]. Set `arbitrary
func_metadata(search, structured_output=True): UNCAUGHT pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for typing.Iterator[str]. Set `arbitrary
Tool.from_function(search): UNCAUGHT pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for typing.Iterator[str]. Set `arbitrary

Full traceback (captured with the collections.abc spelling of the same annotation, so the error names it accordingly):

  File "src/mcp/server/mcpserver/utilities/func_metadata.py", line 444, in func_metadata
    output_model, wrap_output = _create_output_model(original_annotation, return_type_expr, func.__name__)
  File "src/mcp/server/mcpserver/utilities/func_metadata.py", line 550, in _create_output_model
    model = _create_wrapped_model(func_name, original_annotation)
  File "src/mcp/server/mcpserver/utilities/func_metadata.py", line 621, in _create_wrapped_model
    return create_model(model_name, result=annotation)
pydantic.errors.PydanticSchemaGenerationError: Unable to generate pydantic-core schema for collections.abc.Iterator[str]. Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it.

What I expected is what already happens for other unserializable return types, pinned by test_structured_output_unserializable_type_error (tests/server/mcpserver/test_func_metadata.py:1233, passes on main) and documented in docs/servers/structured-output.md: with structured_output=None, registration succeeds and output_schema is None (fallback to text); with structured_output=True, InvalidSignature: Function search: return type ... is not serializable for structured output. For contrast, Iterable[str] and Generator[str, None, None] both register successfully through the same wrapped-model path — only the PEP 484-recommended spellings for generators crash.

Root cause: _create_output_model(...) is called at src/mcp/server/mcpserver/utilities/func_metadata.py:444, outside the try/except at lines 446–470 whose except tuple (PydanticUserError, pydantic_core.SchemaError, ...) exists exactly so that "an unsupported return type surfaces here, at registration" as a clean failure. _create_output_model_create_wrapped_modelcreate_model(model_name, result=annotation) (line 621) builds a schema itself, and its PydanticSchemaGenerationError (a PydanticUserError subclass) escapes uncaught. Moving the line 444 call inside the existing try/except looks like it would restore both documented behaviours; I'd be happy to be assigned and open a PR with that approach.

Related: the guard was added in #2434 (for #1131), but it wraps only the FuncMetadata construction, not this call. #1060 reports the same error class for a different type (Image, 1.x fastmcp) and looks unrelated to this code path.

AI disclosure: this issue and its reproduction were prepared with AI assistance.

Example Code
from typing import Iterator

from mcp.server.mcpserver.tools import Tool
from mcp.server.mcpserver.utilities.func_metadata import func_metadata


def search(n: int) -> Iterator[str]:
    yield from ["a"] * n


for label, call in [
    ("func_metadata(search)", lambda: func_metadata(search)),
    ("func_metadata(search, structured_output=True)", lambda: func_metadata(search, structured_output=True)),
    ("Tool.from_function(search)", lambda: Tool.from_function(search)),
]:
    try:
        call()
        print(f"{label}: OK")
    except Exception as e:
        print(f"{label}: UNCAUGHT {type(e).__module__}.{type(e).__name__}: {str(e)[:80]}")
# AsyncIterator[str] return annotations behave identically
Python & MCP Python SDK
mcp: main @ 6affe5c0d3588fd1705713b3703dc68015cfe3eb
     func_metadata.py is identical in v2.2.0 (latest 2.x release);
     the same crash reproduces on a fresh `pip install mcp==2.2.0`
Python 3.13.15
pydantic 2.12.5
macOS 26.6.2 (arm64)
Lingua principale
Python
Stelle
24.3k
Fork
4k
Merge medio
1g 16h
PR unite (30g)
25

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di modelcontextprotocol/python-sdk

Tutte le issue di modelcontextprotocol/python-sdk

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.