stdio_server: text a tool prints still reaches the client, because sys.stdout is flushed after fd 1 is restored
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 2/5
- Tempo estimado
- 1-3 horas
- Facilidade para iniciantes
- 76/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Ativa
- Stack de tecnologia
- python
- Domínio
- backend-api-design
Direção de pesquisa
Comece lendo a implementação de stdio_server() e rastreando onde fd 1 é redirecionado e restaurado; o issue não menciona um arquivo nem um teste. Reproduza o caso relatado com uma ferramenta que chama print() enquanto stdout está conectado a um pipe e, em seguida, verifique se o texto pendente é enviado para stderr antes de fd 1 ser restaurado e não aparece como uma mensagem JSON-RPC.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
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.
- Linguagem predominante
- Python
- Estrelas
- 24.7k
- Forks
- 4.1k
- Merge médio
- 9h 45min
- PRs com merge (30d)
- 16
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de modelcontextprotocol/python-sdk
-
bug v2
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
modelcontextprotocol/python-sdk#3811 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
bug v2
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 79/100
modelcontextprotocol/python-sdk#3810 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
bug v1 v2
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 79/100
modelcontextprotocol/python-sdk#3781 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
-
[Bug]: Inconsistent structured output wrapping and opt-out for typing.Dict and typing sequence generics in func_metadataTalvez livre de novo Um pull request para esta issue foi fechado sem ser mesclado. Abertabug v1 v2
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
modelcontextprotocol/python-sdk#3771 · 3 comentários ·
Mantenedores costumam responder em até 1 dia
-
bug v2
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 68/100
modelcontextprotocol/python-sdk#3769 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
Todas as issues de modelcontextprotocol/python-sdk
Issues semelhantes
-
fuzz fuzz-unconfirmed
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
Mantenedores costumam responder em até 1 dia
-
ready-for-agent
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 86/100
neilsh/stunt-reel#220 ·
Mantenedores costumam responder em até 1 dia
-
[Issue]: use_fp4_cache is accepted but ignored; the launcher always writes FP8 recordsTalvez já em andamento @0z5a assumiu hoje. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
Mantenedores costumam responder em até 1 dia
-
area: cli priority: p3 size: S type: bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 83/100
finos/open-resource-broker#757 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 65/100
Mantenedores costumam responder em até 6 dias