bhuvan-somisetty opened a new issue, #13987:
URL: https://github.com/apache/apisix/issues/13987

   ### Current Behavior
   
   In `apisix/plugins/mcp-bridge.lua`, the event loop 
(`ctx.mcp_bridge_proc_event_loop`) reads stdout and stderr lines from the 
spawned process via `proc:stdout_read_line()` and `proc:stderr_read_line()`:
   
   ```lua
   local stdout_partial, stderr_partial, need_exit
   while not worker_exiting() do
       repeat
           local line, _
           line, _, stdout_partial = proc:stdout_read_line()
           if line then
               local ok, err = server.transport:send(
                   stdout_partial and stdout_partial .. line or line
               )
               if not ok then
                   core.log.info("session ", server.session_id,
                                 " exit, failed to send response message: ", 
err)
                   need_exit = true
                   break
               end
               stdout_partial = nil -- luacheck: ignore
           end
       until not line
   ```
   
   According to `ngx.pipe` semantics for `proc:stdout_read_line()`:
   - On a full line read: returns `line, nil, nil` (or `line, nil`).
   - On read timeout mid-line: returns `nil, "timeout", partial_data`.
   
   When `proc:stdout_read_line()` times out mid-line (timeouts are configured 
to 100ms via `proc:set_timeouts(nil, 100, 100)`):
   1. `line` is `nil`, and `stdout_partial` is assigned the partial chunk.
   2. Because `line` is `nil`, `if line then` is skipped and `until not line` 
terminates the `repeat` loop.
   3. On the subsequent iteration of `while not worker_exiting() do`, 
`proc:stdout_read_line()` is invoked again:
      `line, _, stdout_partial = proc:stdout_read_line()`
   4. When the remaining portion of the line arrives, `proc:stdout_read_line()` 
returns `line = remaining_line`, `err = nil`, and the 3rd return value is `nil`.
   5. Lua's multiple assignment immediately overwrites `stdout_partial` with 
`nil` (the 3rd return value of `proc:stdout_read_line()`).
   6. `server.transport:send(stdout_partial and stdout_partial .. line or 
line)` evaluates `stdout_partial` as `nil`, sending only `line` (the trailing 
fragment). The buffered partial chunk is permanently lost, causing 
truncated/corrupted JSON-RPC payloads to be sent to the MCP client.
   
   Furthermore:
   - If a line spans multiple timeout intervals, each timeout overwrites 
`stdout_partial` instead of appending to it (`stdout_partial = ...` instead of 
`stdout_partial = (stdout_partial or "") .. ...`).
   - The same issue affects `proc:stderr_read_line()` and `stderr_partial` at 
lines 109–126.
   
   ### Expected Behavior
   
   Partial line buffers should be retained and accumulated across read 
timeouts, and only cleared after successfully concatenating with the completed 
line and dispatching the message to the transport.
   
   ### Error Logs
   
   When a spawned MCP process produces output in chunks across read timeouts, 
the client receives invalid/truncated JSON messages (e.g. missing opening 
attributes or invalid JSON-RPC structures) and fails to parse the response.
   
   ### Steps to Reproduce
   
   1. Configure a route with the `mcp-bridge` plugin executing a command that 
yields JSON-RPC responses in chunks or with pauses longer than 100ms (the pipe 
read timeout).
   2. Connect an MCP client over SSE and invoke a command or tool.
   3. Observe that whenever `proc:stdout_read_line()` experiences a read 
timeout before receiving the newline delimiter, the initial chunk is 
overwritten on the subsequent read, and only the trailing portion is sent to 
the client.
   
   ### Environment
   
   - APISIX version (run `apisix version`): 3.19.0 (master @ 271e799)
   - Operating system (run `uname -a`): Linux / POSIX (all platforms supporting 
`ngx.pipe`)
   - OpenResty / Nginx version (run `openresty -V` or `nginx -V`): OpenResty 
1.25+
   - etcd version, if relevant: N/A
   - APISIX Dashboard version, if relevant: N/A
   - Plugin runner version, for issues related to plugin runners: N/A
   - LuaRocks version, for installation issues: N/A
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to