stdio_server: text a tool prints still reaches the client, because sys.stdout is flushed after fd 1 is restored
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 76/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- python
- Área
- backend-api-design
Línea de trabajo
Empieza leyendo la implementación de stdio_server() y siguiendo dónde se redirige y restaura fd 1; el issue no indica ningún archivo ni prueba. Reproduce el caso informado con una herramienta que llame a print() mientras stdout está canalizado y luego comprueba que el texto pendiente se envía a stderr antes de restaurar fd 1 y no aparece como un mensaje JSON-RPC.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
Since #3117, stdio_server() points fd 1 at stderr while it serves, so that stray output from handlers misses the wire. Text written with print() still reaches the client. It goes into sys.stdout's own buffer, which is block-buffered when stdout is a pipe. That buffer is flushed when the interpreter exits, after stdio_server() has given fd 1 back to the client's pipe. The client then reads the text as a JSON-RPC message.
Reproduction
mcp 2.3.0, Python 3.13.16, macOS 26.3.
import asyncio
import sys
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.server.mcpserver import MCPServer
if sys.argv[1:] == ["server"]:
server = MCPServer("repro")
@server.tool()
def noisy() -> str:
print("stray output from a tool") # e.g. a library that prints
return "done"
server.run("stdio")
else:
async def main():
params = StdioServerParameters(command=sys.executable, args=[__file__, "server"])
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("noisy", {})
print("result:", result.content[0].text)
asyncio.run(main())
Running python repro.py, the call succeeds, and the client also logs:
pydantic_core._pydantic_core.ValidationError: 1 validation error for union[JSONRPCRequest,JSONRPCNotification,JSONRPCResponse,JSONRPCError]
Invalid JSON: expected value at line 1 column 1 [type=json_invalid, input_value='stray output from a tool', input_type=str]
Cause
While fd 1 is diverted, the printed text never reaches it: it sits in sys.stdout's buffer. The buffer is written out at interpreter exit, when fd 1 is the protocol pipe again. Adding sys.stdout.flush() right after the print() in the tool removes the error, and the text appears on stderr, which confirms this.
Suggestion
Flush sys.stdout before restoring fd 1, so that pending text goes to the diversion. Making sys.stdout line-buffered while serving (sys.stdout.reconfigure(line_buffering=True)) would also send printed text to stderr when it is printed, rather than at exit.
As a workaround we call sys.stdout.reconfigure(line_buffering=True) before server.run("stdio") and flush after each tool.
- Lenguaje dominante
- Python
- Estrellas
- 24.7k
- Forks
- 4.1k
- Merge medio
- 9 h 45 min
- PR fusionados (30 d)
- 16
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de modelcontextprotocol/python-sdk
-
bug v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
modelcontextprotocol/python-sdk#3811 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
bug v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 79/100
modelcontextprotocol/python-sdk#3810 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
bug v1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 79/100
modelcontextprotocol/python-sdk#3781 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
[Bug]: Inconsistent structured output wrapping and opt-out for typing.Dict and typing sequence generics in func_metadataQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abiertobug v1 v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
modelcontextprotocol/python-sdk#3771 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
bug v2
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
modelcontextprotocol/python-sdk#3769 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de modelcontextprotocol/python-sdk
Issues similares
-
docs: Release playbookAbiertodocumentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
awslabs/social-messaging-agent-runtime-toolkit#140 ·
Los mantenedores suelen responder en 1 día
-
subtask
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
fga-eps-mds/2026.2-MeasureSoftGram-DOC#187 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 83/100
txn2/mcp-data-platform#2493 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
YO-WHATS-UP2/minigit#78 ·
Los mantenedores suelen responder en 3 días
-
documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
liberation-data/drivine-python#432 ·
Los mantenedores suelen responder en 1 día