|
1 | 1 | import argparse |
2 | 2 | import asyncio |
3 | 3 | import logging |
4 | | -from contextlib import asynccontextmanager |
| 4 | +from contextlib import asynccontextmanager, redirect_stdout |
5 | 5 | import os |
6 | 6 | import sys |
7 | 7 | import threading |
8 | 8 | import time |
9 | 9 | from typing import AsyncIterator, Any |
10 | 10 | from urllib.parse import urlparse |
| 11 | +import io |
| 12 | +from utils.cr_stripper import CRStripper |
11 | 13 |
|
12 | 14 | if sys.platform == 'win32': |
13 | 15 | import msvcrt |
14 | | - import io |
15 | | - |
16 | 16 | # Set binary mode on stdin/stdout to prevent automatic translation at the FD level |
17 | | - msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) |
18 | 17 | msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) |
19 | | - |
20 | | - # Define a proxy buffer that actively strips \r bytes from the output stream |
21 | | - class CRStripper: |
22 | | - def __init__(self, stream): |
23 | | - self._stream = stream |
24 | | - |
25 | | - def write(self, data): |
26 | | - if isinstance(data, bytes): |
27 | | - return self._stream.write(data.replace(b'\r', b'')) |
28 | | - if isinstance(data, str): |
29 | | - return self._stream.write(data.replace('\r', '')) |
30 | | - return self._stream.write(data) |
31 | | - |
32 | | - def flush(self): |
33 | | - return self._stream.flush() |
34 | | - |
35 | | - def __getattr__(self, name): |
36 | | - return getattr(self._stream, name) |
37 | | - |
38 | | - # Detach the underlying buffer from the current sys.stdout |
39 | | - # and re-wrap it with our CRStripper and a new TextIOWrapper |
40 | | - _original_buffer = sys.stdout.detach() |
41 | | - sys.stdout = io.TextIOWrapper( |
42 | | - CRStripper(_original_buffer), |
43 | | - encoding=sys.stdout.encoding or 'utf-8', |
44 | | - errors=sys.stdout.errors or 'strict', |
45 | | - newline='\n', # Enforce LF for text writing |
46 | | - line_buffering=True, |
47 | | - write_through=True |
48 | | - ) |
| 18 | + |
49 | 19 |
|
50 | 20 | from fastmcp import FastMCP |
51 | 21 | from logging.handlers import RotatingFileHandler |
@@ -441,8 +411,16 @@ def main(): |
441 | 411 | mcp.run(transport=transport, host=host, port=port) |
442 | 412 | else: |
443 | 413 | # Use stdio transport for traditional MCP |
444 | | - logger.info("Starting FastMCP with stdio transport") |
445 | | - mcp.run(transport='stdio') |
| 414 | + removed_crlf = io.TextIOWrapper( |
| 415 | + CRStripper(sys.stdout.buffer), |
| 416 | + encoding=sys.stdout.encoding or 'utf-8', |
| 417 | + newline='\n', |
| 418 | + line_buffering=True, |
| 419 | + ) |
| 420 | + |
| 421 | + with redirect_stdout(removed_crlf): |
| 422 | + logger.info("Starting FastMCP with stdio transport") |
| 423 | + mcp.run(transport='stdio') |
446 | 424 |
|
447 | 425 |
|
448 | 426 | # Run the server |
|
0 commit comments