RightNow-AI/openfang · error · io::Error

MCP message too large: {content_length} bytes (max {MAX_MCP_

Error message

MCP message too large: {content_length} bytes (max {MAX_MCP_MESSAGE_SIZE})

What it means

The MCP server reads length-prefixed JSON-RPC messages from stdin and rejects any message whose declared content length exceeds MAX_MCP_MESSAGE_SIZE, returning an InvalidData io::Error (after draining what it can). This guard prevents a peer from forcing unbounded memory allocation via a huge length header.

Source

Thrown at crates/openfang-cli/src/mcp.rs:200

    if content_length == 0 {
        return Ok(None);
    }

    // SECURITY: Reject oversized messages to prevent OOM.
    const MAX_MCP_MESSAGE_SIZE: usize = 10 * 1024 * 1024; // 10MB
    if content_length > MAX_MCP_MESSAGE_SIZE {
        // Drain the oversized body to avoid stream desync
        let mut discard = [0u8; 4096];
        let mut remaining = content_length;
        while remaining > 0 {
            let to_read = remaining.min(4096);
            if reader.read_exact(&mut discard[..to_read]).is_err() {
                break;
            }
            remaining -= to_read;
        }
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("MCP message too large: {content_length} bytes (max {MAX_MCP_MESSAGE_SIZE})"),
        ));
    }

    // Read the body
    let mut body = vec![0u8; content_length];
    reader.read_exact(&mut body)?;

    match serde_json::from_slice(&body) {
        Ok(v) => Ok(Some(v)),
        Err(_) => Ok(None),
    }
}

/// Write a Content-Length framed JSON-RPC response to the writer.
fn write_message(writer: &mut impl Write, msg: &Value) {
    let body = serde_json::to_string(msg).unwrap_or_default();

View on GitHub (pinned to acf2587e46)

Solutions

  1. Split oversized payloads into multiple MCP messages / batch requests so each message stays under MAX_MCP_MESSAGE_SIZE
  2. Inspect what the client is writing to the server's stdin and check the Content-Length framing (length must be the exact byte count of the JSON body, in ASCII digits followed by \r\n)
  3. Raise the server's maximum message size if legitimate messages are genuinely large (configure/increase MAX_MCP_MESSAGE_SIZE in crates/openfang-cli/src/mcp.rs) and restart the daemon
  4. Check the client library version for known framing bugs; upgrade or downgrade to a version that frames messages correctly
  5. Validate and sanitize upstream data (truncate tool outputs) before sending them over MCP

Example fix

// before (client sends one huge message)
let body = serde_json::to_vec(&huge_request)?; // e.g. 50 MB tool result
write_message(stdout, &body)?;
// after (truncate/summarize before sending)
let body = serde_json::to_vec(&truncate_request(&huge_request, 1_000_000))?;
write_message(stdout, &body)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// client-side, before writing a message to the MCP server's stdin
let body = serde_json::to_vec(&request)?;
if body.len() > MAX_MCP_MESSAGE_SIZE {
    return Err(anyhow!("payload {} bytes exceeds MCP max {}; truncate or split", body.len(), MAX_MCP_MESSAGE_SIZE));
}

Type guard

fn message_size_ok(body: &[u8], max: usize) -> bool { body.len() <= max }

Try / catch

match write_message(child.stdin.as_mut().unwrap(), &body) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains("too large") => {
        eprintln!("MCP message over the size cap; truncate tool output or split the request");
        // fall back to a summarized/shorter request
    }
    other => other?,
}

Prevention

When it happens

Trigger: An MCP client sends a Content-Length header larger than MAX_MCP_MESSAGE_SIZE: a malicious or buggy client, a corrupted/framed stream where a payload byte is misread as a length digit, a client that does not chunk or truncate large tool results, or a proxy mangling framing so the length field is garbage.

Common situations: Piping large files or long tool outputs through an MCP client; a misbehaving LLM client library that serializes huge tool results in one message; feeding raw logs into the server's stdin; running an old/new client against a server with a different size cap.

Related errors


AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02). Data as JSON: /api/errors/aea93b7202fa2b09. Report an issue: GitHub.