Summary
MCP tools backed by ReadFirstSSEMessage fail with error reading SSE stream: bufio.Scanner: token too long whenever the upstream SSE data: line exceeds Go's default bufio.MaxScanTokenSize (64 KiB).
Reproduction
Ask an LLM agent (via kubewall MCP server) something like:
give me list of top 10 memory consumption pods
In any cluster with a non-trivial number of pods, the resulting list serialized into a single SSE data: line exceeds 64 KiB and the scanner aborts.
Error
error reading SSE stream: bufio.Scanner: token too long
Surfaces to the LLM as a mcp.NewToolResultError(...), breaking the tool call.
Root cause
backend/handlers/mcp/helpers/helpers.go:24-57 — ReadFirstSSEMessage:
scanner := bufio.NewScanner(resp.Body)
// ... no scanner.Buffer() override
if err := scanner.Err(); err != nil {
return "", fmt.Errorf("error reading SSE stream: %w", err)
}
bufio.NewScanner defaults to a 64 KiB max token size. The internal SSE producer emits the entire list/YAML payload as a single data: line, so any reasonably sized resource set blows the limit and scanner.Err() returns bufio.ErrTooLong.
Affected call sites
backend/handlers/mcp/tools/tools.go:78 — *List tools (e.g. podsList, nodesList, …)
backend/handlers/mcp/tools/tools.go:128 — *YamlDetails tools (large YAML payloads also break)
backend/handlers/mcp/tools/logs.go:102 — same default-buffer pattern; will break on a single long log line
backend/handlers/workloads/pods/logs.go:50, 169 — same default-buffer pattern in pod log streaming
Proposed fix
Raise the scanner's max buffer at every usage:
scanner := bufio.NewScanner(resp.Body)
scanner.Buffer(make([]byte, 0, 8*1024), 10*1024*1024) // 8 KiB initial, 10 MiB max
8 KiB initial keeps the common-case allocation small; 10 MiB cap matches what large LLM-gateway projects (e.g. Bifrost's core/providers/utils/sse.go) use for the same reason — it covers realistic SSE payloads (large lists, tool-call JSON, base64 blobs) without exposing an unbounded-memory footgun.
Alternatively, switch to bufio.Reader.ReadBytes('\n') / a streaming SSE parser that has no per-line size limit.
Impact
Any user running an LLM agent against a real-world cluster (more than a handful of pods/nodes/etc.) hits this for *List and *YamlDetails MCP tools, making the kubewall MCP server effectively unusable for typical workloads.
Environment
- kubewall: latest
main (helper code unchanged for a while)
- Triggered through an LLM tool call to
podsList-class tooling
Summary
MCP tools backed by
ReadFirstSSEMessagefail witherror reading SSE stream: bufio.Scanner: token too longwhenever the upstream SSEdata:line exceeds Go's defaultbufio.MaxScanTokenSize(64 KiB).Reproduction
Ask an LLM agent (via kubewall MCP server) something like:
In any cluster with a non-trivial number of pods, the resulting list serialized into a single SSE
data:line exceeds 64 KiB and the scanner aborts.Error
Surfaces to the LLM as a
mcp.NewToolResultError(...), breaking the tool call.Root cause
backend/handlers/mcp/helpers/helpers.go:24-57—ReadFirstSSEMessage:bufio.NewScannerdefaults to a 64 KiB max token size. The internal SSE producer emits the entire list/YAML payload as a singledata:line, so any reasonably sized resource set blows the limit andscanner.Err()returnsbufio.ErrTooLong.Affected call sites
backend/handlers/mcp/tools/tools.go:78—*Listtools (e.g.podsList,nodesList, …)backend/handlers/mcp/tools/tools.go:128—*YamlDetailstools (large YAML payloads also break)backend/handlers/mcp/tools/logs.go:102— same default-buffer pattern; will break on a single long log linebackend/handlers/workloads/pods/logs.go:50, 169— same default-buffer pattern in pod log streamingProposed fix
Raise the scanner's max buffer at every usage:
8 KiB initial keeps the common-case allocation small; 10 MiB cap matches what large LLM-gateway projects (e.g. Bifrost's
core/providers/utils/sse.go) use for the same reason — it covers realistic SSE payloads (large lists, tool-call JSON, base64 blobs) without exposing an unbounded-memory footgun.Alternatively, switch to
bufio.Reader.ReadBytes('\n')/ a streaming SSE parser that has no per-line size limit.Impact
Any user running an LLM agent against a real-world cluster (more than a handful of pods/nodes/etc.) hits this for
*Listand*YamlDetailsMCP tools, making the kubewall MCP server effectively unusable for typical workloads.Environment
main(helper code unchanged for a while)podsList-class tooling