Bare `dict` / `list` / `tuple` return annotations silently produce no structured output
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 72/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- python
- Ambito
- backend-api-design
Direzione di ricerca
Inizia leggendo _create_output_model in src/mcp/server/mcpserver/utilities/func_metadata.py e la documentazione sull’output strutturato in docs/servers/structured-output.md. Riproduci la differenza tra annotazioni di contenitore semplici e tipizzate, quindi controlla i test esistenti per gli schemi di output e i contenuti strutturati. Il lavoro è terminato quando le annotazioni semplici di dict, list e tuple hanno il comportamento previsto per l’output strutturato e la documentazione lo spiega.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Initial Checks
- I confirm that I'm using the newest release of my line (the latest 2.x, or the latest 1.x if I'm still on v1)
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
Release line
2.x (current stable)
Description
A tool annotated with a bare dict (or list / tuple) gets no outputSchema and no structuredContent. The result only arrives as JSON text. -> dict[str, Any] works, and -> str gets {"result": ...}. With structured_output=True the bare annotation raises InvalidSignature: Function f: return type <class 'dict'> is not serializable for structured output, which reads as if a dict weren't serializable.
Expected: -> dict behaves like dict[str, Any], and -> list / -> tuple like list[Any] (wrapped in {"result": ...}). Failing that, the structured-output docs could say that bare containers opt out.
Cause: _create_output_model sends bare dict / list / tuple to the "other class types" case. get_type_hints(dict) is empty, so the model stays None: the silent opt-out documented for classes without type hints, which isn't obvious for builtins. We hit it while building an MCP server: our tools were -> dict, and our client code expected structured_content that was always None.
Proposed fix: a case before the class fallback that sends bare dict down the dict[str, ...] path and wraps bare list / tuple like their generic forms, plus a test and one sentence in docs/servers/structured-output.md. It's about 10 lines of code, and the full suite passes (6206 passed). One behaviour change to weigh: existing bare -> dict / -> list tools would start publishing an outputSchema and validating their results.
I'd like to send this as a PR if you're open to it. It's on a branch: https://github.com/g-s-jithesh/python-sdk/commit/6ecfa04ece6032816c7d3a087fd8c841cb0c43e1
I used an AI coding assistant (Claude Code) to help investigate this and draft the fix. I reproduced the bug myself and reviewed the change.
Example Code
import asyncio
from typing import Any
from mcp import Client
from mcp.server.mcpserver import MCPServer
mcp = MCPServer("repro")
@mcp.tool()
def bare() -> dict:
return {"id": 1}
@mcp.tool()
def typed() -> dict[str, Any]:
return {"id": 1}
async def main() -> None:
async with Client(mcp) as client:
for name in ("bare", "typed"):
print(name, (await client.call_tool(name, {})).structured_content)
asyncio.run(main())
# bare None
# typed {'id': 1}
Python & MCP Python SDK
Python 3.14, Windows 11; mcp 2.3.0, and main at 9f66f37 (src/mcp/server/mcpserver/utilities/func_metadata.py, _create_output_model)
- Lingua principale
- Python
- Stelle
- 24.5k
- Fork
- 4k
- Merge medio
- 18h
- PR unite (30g)
- 39
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di modelcontextprotocol/python-sdk
-
bug v1 v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
modelcontextprotocol/python-sdk#3698 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Streamable HTTP: Content-Type handling is order dependent and accepts invalid valuesForse già presa @jayzuccarelli l’ha presa 6 giorni fa. Apertabug v1 v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
modelcontextprotocol/python-sdk#3691 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Skills: URI traversal validation skips percent-encoded dot-segmentsForse già presa @Varshith-Kali l’ha presa 5 giorni fa. Apertabug v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
modelcontextprotocol/python-sdk#3685 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Type annotation gaps and unhandled FileNotFoundError in src/mcp/cli/cli.pyForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Apertaenhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
modelcontextprotocol/python-sdk#3673 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Streamable HTTP server rejects a mixed-case Content-Type with 415Forse di nuovo libera @CRYPTONIKAV l’ha presa 8 giorni fa e non c’è nessuna pull request aperta. Apertabug v1 v2
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
modelcontextprotocol/python-sdk#3670 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di modelcontextprotocol/python-sdk
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
SACGF/variantgrid#2341 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 2 giorni
-
comp/cli P3 type/security
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
NousResearch/hermes-agent#141420 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
CKV_GCP_18 (GKEPublicControlPlane) passes when master_authorized_networks_config is absent, control plane is internet-reachableForse già presa @Varshith-Kali l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
bridgecrewio/checkov#7753 ·
I maintainer di solito rispondono entro 1 giorno