Summary
In McpServer.ProcessLineAsync (McpServer.cs:66-71 and ~102-106), the outer try/catch logs an uncaught exception to stderr before writing the JSON-RPC error response back to the client. If the client times out between the log write and the response write (e.g. on a long-running tool call that the client gave up on), the operator sees an error in the server log but the client may never receive a response, making the failure look like a hang rather than an error. Also, when HandleMessage returns a JsonNode representing an error, the path doesn't include the failing request's id reliably in all branches, so clients can struggle to correlate the error to the request that caused it.
Where
Suggested approach
(1) Reorder: build the error response with the request's id first, write it to stdout, then log to stderr — so even if the client closes the connection mid-flight, the response was at least attempted before logging. (2) Always echo the request id in the error response, even when parsing fails before extracting the id (use a null id per JSON-RPC 2.0 spec). (3) Wrap the response-write itself in its own try/catch and log a second line if even the response write fails (broken pipe etc.). (4) Add a regression test: malformed JSON, oversized payload, exception thrown from inside a tool handler — each should produce a stdout response and a stderr log line in that order. (5) Cross-link with #1493, #1720, #1418, #1898.
Summary
In
McpServer.ProcessLineAsync(McpServer.cs:66-71 and ~102-106), the outer try/catch logs an uncaught exception to stderr before writing the JSON-RPC error response back to the client. If the client times out between the log write and the response write (e.g. on a long-running tool call that the client gave up on), the operator sees an error in the server log but the client may never receive a response, making the failure look like a hang rather than an error. Also, whenHandleMessagereturns a JsonNode representing an error, the path doesn't include the failing request'sidreliably in all branches, so clients can struggle to correlate the error to the request that caused it.Where
src/CodeIndex/Mcp/McpServer.cs:66-71(ProcessLineAsync exception path)src/CodeIndex/Mcp/McpServer.cs:~102-106(HandleMessage call site)Suggested approach
(1) Reorder: build the error response with the request's
idfirst, write it to stdout, then log to stderr — so even if the client closes the connection mid-flight, the response was at least attempted before logging. (2) Always echo the requestidin the error response, even when parsing fails before extracting the id (use anullid per JSON-RPC 2.0 spec). (3) Wrap the response-write itself in its own try/catch and log a second line if even the response write fails (broken pipe etc.). (4) Add a regression test: malformed JSON, oversized payload, exception thrown from inside a tool handler — each should produce a stdout response and a stderr log line in that order. (5) Cross-link with #1493, #1720, #1418, #1898.