Problem
Large successful tool results with output schemas can become protocol-invalid after response limiting.
FastMCP stores structured output in both content and structuredContent, then the response limiter measures the serialized whole result. libtmux-mcp uses a 50 KB backstop on large-output tools. When the limiter fires, the returned result can lose structuredContent, and FastMCP clients raise:
RuntimeError: Tool capture_pane has an output schema but did not return structured content
Minimal local reproduction
$ uv run python - <<'PY'
import asyncio
import uuid
from fastmcp import Client
from libtmux_mcp.server import build_mcp_server
from libtmux_mcp._utils import _get_server
async def main():
socket_name = f"limit_{uuid.uuid4().hex[:8]}"
server = _get_server(socket_name=socket_name)
session = server.new_session(session_name="limit", kill_session=True, attach=False)
pane = session.active_pane
try:
pane.send_keys("for i in $(seq 1 1400); do printf 'line%04d xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\\n' $i; done", enter=True)
await asyncio.sleep(1.5)
async with Client(build_mcp_server()) as client:
await client.call_tool("capture_pane", {
"pane_id": pane.pane_id,
"socket_name": socket_name,
"start": -1400,
"max_lines": None,
})
finally:
server.kill()
asyncio.run(main())
PY
Expected today: the client raises because the truncated response has no structured content.
Upstream mechanism
Minimal fix
Do not truncate schema-bearing success results into text-only results.
Preferred minimal path:
- Raise the middleware backstop above every tool-level cap.
- Keep truncation inside each tool's structured model fields (
truncated, content, lines, etc.).
- Preserve
structuredContent for all successful output-schema tools.
Acceptance criteria
- Large
capture_pane, capture_since, snapshot_pane, and search_panes calls return valid structured content.
- FastMCP
Client.call_tool() does not raise for large successful captures.
- Tests cover a large successful schema-bearing result through the client path.
Problem
Large successful tool results with output schemas can become protocol-invalid after response limiting.
FastMCP stores structured output in both
contentandstructuredContent, then the response limiter measures the serialized whole result. libtmux-mcp uses a 50 KB backstop on large-output tools. When the limiter fires, the returned result can losestructuredContent, and FastMCP clients raise:Minimal local reproduction
Expected today: the client raises because the truncated response has no structured content.
Upstream mechanism
structuredContentfromToolResult: https://github.com/jlowin/fastmcp/blob/v3.4.2/fastmcp_slim/fastmcp/tools/base.py#L143Minimal fix
Do not truncate schema-bearing success results into text-only results.
Preferred minimal path:
truncated,content,lines, etc.).structuredContentfor all successful output-schema tools.Acceptance criteria
capture_pane,capture_since,snapshot_pane, andsearch_panescalls return valid structured content.Client.call_tool()does not raise for large successful captures.