|
5 | 5 | import anyio |
6 | 6 | import pytest |
7 | 7 |
|
| 8 | +import mcp.server.stdio as stdio_module |
8 | 9 | from mcp.server.stdio import stdio_server |
9 | 10 | from mcp.shared.message import SessionMessage |
10 | 11 | from mcp.types import JSONRPCMessage, JSONRPCRequest, JSONRPCResponse, jsonrpc_message_adapter |
@@ -92,3 +93,29 @@ async def test_stdio_server_invalid_utf8(monkeypatch: pytest.MonkeyPatch): |
92 | 93 | second = await read_stream.receive() |
93 | 94 | assert isinstance(second, SessionMessage) |
94 | 95 | assert second.message == valid |
| 96 | + |
| 97 | + |
| 98 | +@pytest.mark.anyio |
| 99 | +async def test_stdio_server_disables_newline_translation(monkeypatch: pytest.MonkeyPatch): |
| 100 | + raw_stdin = io.BytesIO() |
| 101 | + raw_stdout = io.BytesIO() |
| 102 | + |
| 103 | + monkeypatch.setattr(sys, "stdin", TextIOWrapper(raw_stdin, encoding="utf-8")) |
| 104 | + monkeypatch.setattr(sys, "stdout", TextIOWrapper(raw_stdout, encoding="utf-8")) |
| 105 | + |
| 106 | + calls: list[dict[str, object | None]] = [] |
| 107 | + real_text_io_wrapper = TextIOWrapper |
| 108 | + |
| 109 | + def spy(buffer: io.BufferedIOBase, *args: object, **kwargs: object) -> TextIOWrapper: |
| 110 | + calls.append({"errors": kwargs.get("errors"), "newline": kwargs.get("newline")}) |
| 111 | + return real_text_io_wrapper(buffer, *args, **kwargs) |
| 112 | + |
| 113 | + monkeypatch.setattr(stdio_module, "TextIOWrapper", spy) |
| 114 | + |
| 115 | + with anyio.fail_after(5): |
| 116 | + async with stdio_server() as (read_stream, write_stream): |
| 117 | + await write_stream.aclose() |
| 118 | + await read_stream.aclose() |
| 119 | + |
| 120 | + assert {"errors": "replace", "newline": ""} in calls |
| 121 | + assert {"errors": None, "newline": ""} in calls |
0 commit comments