From e6165d23bb2f2df4b25aa791aaac3a81cd835b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Arrufat?= Date: Thu, 27 Aug 2026 14:53:32 +0200 Subject: [PATCH] mcp: release a large HTTP response buffer after the reply The transport already drops its staging buffer past 256 KB, but the connection buffer that receives the copy lives for the whole keep-alive connection and was only ever cleared, so one screenshot pinned its capacity per open connection. Apply the same threshold there. Claude-Session: https://claude.ai/code/session_01S9t1TX3vTKunaXdnatbcjB --- src/mcp/HttpServer.zig | 5 +++++ src/mcp/Transport.zig | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mcp/HttpServer.zig b/src/mcp/HttpServer.zig index e1394cd4a..744d9c332 100644 --- a/src/mcp/HttpServer.zig +++ b/src/mcp/HttpServer.zig @@ -35,6 +35,7 @@ const App = @import("../App.zig"); const sys_net = @import("../sys/net.zig"); const Server = @import("Server.zig"); +const Transport = @import("Transport.zig"); const router = @import("router.zig"); const log = lp.log; @@ -379,6 +380,10 @@ fn handleConn(self: *HttpServer, socket: posix.socket_t) void { _ = arena.reset(.retain_capacity); out.clearRetainingCapacity(); self.serve(&out.writer, arena.allocator(), &request) catch return; + if (out.writer.buffer.len > Transport.large_response) { + out.deinit(); + out = .init(self.allocator); + } if (!request.head.keep_alive or http_server.reader.state == .closing) return; } } diff --git a/src/mcp/Transport.zig b/src/mcp/Transport.zig index e81bae88f..eb94045f7 100644 --- a/src/mcp/Transport.zig +++ b/src/mcp/Transport.zig @@ -25,7 +25,8 @@ const protocol = @import("protocol.zig"); const Self = @This(); -const large_response = 256 * 1024; +/// A screenshot response is hundreds of KB; don't keep that parked. +pub const large_response = 256 * 1024; writer: *std.Io.Writer, mutex: std.Io.Mutex = .init, @@ -56,7 +57,6 @@ pub fn sendResponse(self: *Self, response: anytype) !void { try self.writer.writeAll(self.aw.writer.buffered()); try self.writer.flush(); - // A screenshot response is hundreds of KB; don't keep that parked. if (self.aw.writer.buffer.len > large_response) { const allocator = self.aw.allocator; self.aw.deinit();