pi-mono/packages/mcp/test
robopipi[bot] f6278a472e
fix(mcp): read large stdio messages in linear time (#11791)
`JsonRpcLineReader.readStdout` (used by the stdio transport and by
`PipeTransport`) appended every stdout chunk to the buffered bytes with
`Buffer.concat`, then searched the whole buffer from the start for a
newline. A large message arriving in many chunks was therefore copied
and scanned again on every chunk. A 12 MiB tool result in 64 KiB chunks
took about 350 ms just to frame.

Now the reader keeps the bytes of an incomplete message as a list of
chunks, with a running byte count, and searches only the new chunk for a
newline. When the newline arrives, the chunks are joined once. A line
that fits inside a single chunk is sliced directly. The rest is
unchanged: the `maxMessageBytes` limit (now checked against the running
count), CRLF and blank-line handling, errors for invalid JSON and
oversized messages, and the incomplete-message error in `end()`.

Testing:
- New `packages/mcp/test/lines.test.ts`:
- a 1 MiB message fed in 4 KiB chunks calls `Buffer.concat` once (fails
on the old code);
- a mixed input of multi-byte UTF-8, CRLF, blank lines, an invalid line
and several messages gives the same results at every chunk size from 1
byte to the whole input;
  - reading recovers after an oversized message;
  - a message without its newline is reported at the end.
- `test/lines.test.ts`, `test/stdio.test.ts` and `test/pipe.test.ts`
pass. `npm run check` passes.
- Micro-benchmark, one message fed in 64 KiB chunks:
  - before: 1 MiB 5.4 ms, 4 MiB 49.9 ms, 12 MiB 348 ms;
  - after: 2.2 ms, 7.9 ms, 21.6 ms.

Fixes #11761

Requested by @badlogic

Co-authored-by: triagent <triagent@localhost>
2026-11-04 10:09:23 +01:00
..
fixtures fix(mcp): clean up server children on stdio close after the server exited (#11724) 2026-11-03 09:31:10 +01:00
auth-provider.test.ts fix(mcp): refresh with the app's redirect URI, cancel sign-in during the lock wait 2026-11-03 14:17:21 +01:00
authorization-server.ts fix(mcp): refresh with the app's redirect URI, cancel sign-in during the lock wait 2026-11-03 14:17:21 +01:00
client.test.ts fix(mcp,coding-agent): accept any JSON value as tool structuredContent 2026-10-12 14:16:35 +02:00
config.test.ts feat(mcp): shared tool naming, schema, output limit and config helpers 2026-11-03 14:17:21 +01:00
content.test.ts fix(mcp,coding-agent): accept any JSON value as tool structuredContent 2026-10-12 14:16:35 +02:00
helpers.ts feat(coding-agent): codemode and MCP 2026-09-29 09:12:50 +02:00
input-schema.test.ts feat(mcp): shared tool naming, schema, output limit and config helpers 2026-11-03 14:17:21 +01:00
lines.test.ts fix(mcp): read large stdio messages in linear time (#11791) 2026-11-04 10:09:23 +01:00
loopback.test.ts feat(mcp): MCP OAuth sign-in in two halves, moved from coding-agent 2026-11-03 14:17:21 +01:00
naming.test.ts feat(mcp): shared tool naming, schema, output limit and config helpers 2026-11-03 14:17:21 +01:00
oauth.test.ts fix(mcp): accept only http and https OAuth URLs 2026-10-23 12:19:56 +02:00
output-limit.test.ts feat(mcp): shared tool naming, schema, output limit and config helpers 2026-11-03 14:17:21 +01:00
pipe.test.ts feat(mcp): PipeTransport, the stdio transport over a program started by the caller 2026-11-03 14:17:21 +01:00
sign-in.test.ts fix(mcp): refresh with the app's redirect URI, cancel sign-in during the lock wait 2026-11-03 14:17:21 +01:00
stdio.test.ts fix(mcp): clean up server children on stdio close after the server exited (#11724) 2026-11-03 09:31:10 +01:00
streamable-http.test.ts fix(mcp): recognize CR-only line endings in Streamable HTTP SSE (#11775) 2026-11-04 09:18:01 +01:00