# libtmux_mcp.middleware.TailPreservingResponseLimitingMiddleware

- **Module:** libtmux_mcp.middleware
- **Package:** libtmux-mcp
- **Language:** Python
- **Kind:** class
- **Source:** https://github.com/tmux-python/libtmux-mcp/blob/4daddc0dfca96c43bf521d818bf91564e1434760/src/libtmux_mcp/middleware.py#L742
- **Page:** https://libtmux.org/en/py/latest/mcp/reference/libtmux_mcp-middleware-tailpreservingresponselimitingmiddleware/

Response-limiter that keeps the tail of oversized output.

FastMCP's stock ``ResponseLimitingMiddleware`` truncates the
tail of the response (keeps the start, appends a suffix). That's
exactly wrong for terminal scrollback, where the active shell
prompt and most recent command output live at the **bottom** of
the buffer. This subclass overrides ``_truncate_to_result`` to
drop the head instead, prefixing a single truncation-header line
so callers can detect the cap fired.

Used as a backstop for :func:`libtmux_mcp.tools.pane_tools.capture_pane`,
:func:`libtmux_mcp.tools.pane_tools.capture_since`,
:func:`libtmux_mcp.tools.pane_tools.snapshot_pane`, and
:func:`libtmux_mcp.tools.pane_tools.search_panes`, plus
:func:`libtmux_mcp.tools.buffer_tools.show_buffer`. Per-tool caps at
the tool layer fire first under normal operation; this middleware
catches a missed bound within that configured high-volume set.

Error results keep their ``is_error`` flag through truncation.
The stock truncation path rebuilds the result without it, which
turns an oversized error (e.g. a validation message echoing a
huge argument) into an apparent success — MCP clients then
validate the truncated text against the tool's output schema and
fail with a transport-level error instead of delivering the tool
error. ``meta`` (``error_type`` / ``expected`` / ``suggestion``)
already survives via the base class, and tail-preservation keeps
the suggestion line, which sits at the end of the text.

## Members

- `on_call_tool` (method): Apply the size cap without dropping ``is_error``.
