Skip to content

Commit 50251a3

Browse files
committed
fix(proxy): use read1 so MCP frames forward without 64KB block
The parent->child stdio pump was using src.read(64*1024) which on a BufferedReader-backed pipe (subprocess stdin, sys.stdin.buffer) blocks until exactly 64 KB arrive or EOF. MCP JSON-RPC frames are hundreds of bytes — so they sit in the buffer waiting for more data that never comes, and the child engine never sees any input from BioRouter. The unit tests passed because BytesIO.read(n) returns immediately with whatever's available, masking the bug. Switched to src.read1(n) which has the correct streaming semantics on real pipes AND remains compatible with BytesIO.
1 parent 48aa2da commit 50251a3

1 file changed

Lines changed: 9 additions & 1 deletion

File tree

src/codegraphagent/proxy.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,22 @@
2222
def _pump(src: BinaryIO, dst: BinaryIO, *, close_dst_on_eof: bool = False) -> None:
2323
"""Copy bytes from src to dst until src is closed/EOF.
2424
25+
Uses ``read1`` (not ``read``) so partial reads forward immediately. For a
26+
BufferedReader backed by a pipe (subprocess stdin/stdout, sys.stdin.buffer),
27+
``read(n)`` blocks until exactly n bytes arrive or EOF — fatal for MCP
28+
framing where JSON-RPC frames are hundreds of bytes, far short of the
29+
64 KB chunk size. ``read1(n)`` returns whatever the underlying stream has
30+
available in one read, which is the correct streaming behavior.
31+
2532
If `close_dst_on_eof` is True, closes dst when src returns EOF — needed for
2633
the parent_stdin → child_stdin direction so the engine sees EOF and exits
2734
cleanly when BioRouter closes its end. The child→parent directions leave
2835
dst open so the parent process can flush other output.
2936
"""
37+
read1 = getattr(src, "read1", src.read)
3038
try:
3139
while True:
32-
chunk = src.read(_PUMP_CHUNK)
40+
chunk = read1(_PUMP_CHUNK)
3341
if not chunk:
3442
break
3543
dst.write(chunk)

0 commit comments

Comments
 (0)