Hmbown/CodeWhale · error

MCP response body exceeds

Error message

MCP response body exceeds {max_bytes} bytes — aborting

What it means

The streamable-HTTP MCP transport caps response body reads at max_bytes. While streaming the response body, if accumulating another chunk would exceed the cap the read is aborted with this error, protecting the client from unbounded or malicious responses.

Solutions

  1. Increase the MCP response body size cap in configuration if legitimate responses are large.
  2. Reduce the size of tool outputs on the server side (paginate, truncate).
  3. Check the server for a bug that returns oversized non-JSON bodies.
  4. If the endpoint is untrusted, treat this as the size guard working as intended and investigate the server.

Example fix

// before: cap too small for large tool outputs
let max_bytes = 64 * 1024;

// after
let max_bytes = 4 * 1024 * 1024;
Defensive patterns

Strategy: validation

Validate before calling

if expected_max_response > configured_max_bytes {
    raise ConfigError("response cap smaller than expected tool outputs; raise the cap")
}

Try / catch

Err(e) if e.to_string().contains("body exceeds") => {
    // treat as untrusted/oversized response: do not retry blindly;
    // raise cap only if the server is trusted and outputs are legitimately large
    return Err(anyhow!("oversized MCP response; cap={}, check server output size", e));
}

Prevention

When it happens

Trigger: An MCP server returns a response body larger than the configured cap while send() drains the bytes_stream — e.g. a huge tool result, a server bug returning an error page as a giant body, or a compromised/hostile endpoint.

Common situations: Tool returning enormous output (large file dumps, log spew); misconfigured cap set below the server's legitimate response size; server streaming an error document without a proper HTTP error status.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/8b644e9e5d965ada. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/mcp/streamable_http.rs:228

}

/// Read a response body through the byte stream, failing as soon as it
/// exceeds `max_bytes`. This bounds chunked and missing-Content-Length
/// responses exactly like declared ones (the declared-length fast path in
/// `send` only covers servers honest enough to announce their size).
/// MCP bodies are JSON or SSE, so lossy UTF-8 matches `.text()` behavior.
pub(super) async fn read_body_capped(
    response: reqwest::Response,
    max_bytes: usize,
) -> Result<String> {
    use futures_util::StreamExt;

    let mut stream = response.bytes_stream();
    let mut buf: Vec<u8> = Vec::new();
    while let Some(chunk) = stream.next().await {
        let chunk = chunk.context("failed to read MCP response body")?;
        if buf.len().saturating_add(chunk.len()) > max_bytes {
            anyhow::bail!("MCP response body exceeds {max_bytes} bytes — aborting");
        }
        buf.extend_from_slice(&chunk);
    }
    Ok(String::from_utf8_lossy(&buf).into_owned())
}

/// TUI recovery for a rejected OAuth session. Settings recovery and the
/// Streamable HTTP path share the oauth helpers so `/mcp login <name>` stays
/// the only advertised command; `/mcp auth` is not a command.
fn oauth_refresh_failed_hint() -> &'static str {
    super::oauth::tui_reauth_refresh_failed_hint()
}

/// TUI recovery for a rejected OAuth session. `oauth_configured` is the
/// server's configured auth path ([`McpHttpAuth::oauth_configured`]), not the
/// presence of a cached token, so a first-run OAuth server — a 401 with
/// nothing stored yet — is still pointed at `/mcp login <name>` rather than at
/// a bearer token it never had (#6030). Servers where a bearer credential is

View on GitHub (pinned to 73e0f67d83)