modelcontextprotocol / modelcontextprotocol/python-sdk

stdio_client crashes on malformed UTF-8 from child stdout instead of surfacing parse error

Abierto
#2,454 3 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

bug fix proposed P2 ready for work
Lenguaje dominante
Python
Estrellas
24.3k
Forks
4k
Merge medio
1 d 1 h
PR fusionados (30 d)
31

Descripción

Summary

mcp.client.stdio.stdio_client() crashes when the spawned child process writes invalid UTF-8 bytes to stdout.

The transport currently decodes child stdout with encoding_error_handler="strict", so malformed bytes raise during TextReceiveStream(...) iteration. That exception escapes the decoding loop and brings down the transport task group instead of surfacing the bad line as an in-stream parse error.

Why this looks like a bug

The SDK already hardened the server side for the analogous case in PR #2302 (fix: handle non-UTF-8 bytes in stdio server stdin). That change explicitly preferred:

  • replace invalid bytes with U+FFFD,
  • let JSON validation fail on the malformed line, and
  • keep the transport alive so subsequent valid messages can still be processed.

The client side still behaves asymmetrically today. A buggy or non-compliant child server can kill the Python client transport with a single malformed line even if the next line is valid JSON-RPC.

That seems inconsistent with the current stdio robustness direction.

Reproduction

A minimal child process that writes one malformed line and then one valid JSON-RPC line:

import sys
import time

sys.stdout.buffer.write(b"\xff\xfe\n")
sys.stdout.buffer.write(b'{"jsonrpc":"2.0","id":1,"method":"ping"}\n')
sys.stdout.buffer.flush()
time.sleep(0.2)

With current stdio_client(...) defaults, the transport raises ExceptionGroup instead of continuing.

Expected behavior

The malformed line should be surfaced as an in-stream parse / validation error, and the next valid JSON-RPC line should still be received.

Observed behavior

The transport task group fails before the valid follow-up message is delivered.

Proposed fix

Match the server-side approach from PR #2302:

  1. default StdioServerParameters.encoding_error_handler to "replace"
  2. continue treating malformed decoded lines as JSON validation failures
  3. keep the background stdio tasks resilient during early subprocess shutdown / abrupt close

Validation

I reproduced this locally against current main and verified that a minimal patch plus a regression test fixes it.

A focused regression test in tests/client/test_stdio.py can assert:

  • first item from the read stream is an Exception
  • second item is the valid SessionMessage

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Empieza en mcp.client.stdio.stdio_client() y tests/client/test_stdio.py; revisa cómo la decodificación de TextReceiveStream y la iteración del flujo de lectura gestionan los errores de codificación. Añade la regresión de formato malformado-y-válido descrita en el issue y ejecuta el test enfocado para verificar que el primer elemento es una Exception, el segundo una SessionMessage válida y que el transporte sigue activo.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
backend, testing
Tipo de issue
Error
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Tranquilo
Claridad
Bien especificado
Aptitud para principiantes
78/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.