#47506·envoy

content-length: 0 stripped from empty local-reply bodies via prepareLocalReply, blocks mcp_json_rest_bridge's notifications/initialized ack

Author: kkukadiaCreated Sep 17, 2026Updated Sep 17, 2026

cc @guoyilin42 — this is about the TODO you left at line 968.

There's a TODO at mcp_json_rest_bridge_filter.cc:968:

cc
// TODO(guoyilin42): We may need to explicitly set `content-length: 0` to prevent curl from
// hanging. `modify_headers` fails here as `sendLocalReply` removes it for empty bodies.

The ack for notifications/initialized sends an empty 202 with no modify_headers callback (it's nullptr), because the TODO already anticipated that passing one wouldn't help.

In Utility::prepareLocalReply (source/common/http/utility.cc), modify_headers_ runs first, but then for an empty, non-gRPC body the code unconditionally calls removeContentLength() and removeContentType() afterward. So even if the filter did set content-length: 0 through the callback, prepareLocalReply would strip it right after. Since that removal happens after the filter's callback runs, the fix has to live outside the filter.

Questions:

  1. Should the ack carry a small non-empty body, so content-length gets set the normal way?
  2. If it must stay empty, should prepareLocalReply emit content-length: 0 for empty non-gRPC replies instead of removing it, or should the removal become conditional?
  3. Is this actually a codec-level expectation? A 202 isn't a bodiless-by-spec status, so the HTTP/1 codec would normally add content-length: 0 on an empty end-stream response. If so, the curl hang might point elsewhere.

Happy to send a PR once there's agreement on where the fix is.