What happened?
With ResponseLimitingMiddleware(max_size=1000), responses over the limit get truncated, but the truncated response still serializes to more than max_size. A plain-ASCII response comes out at ~1.2× the limit; escape-heavy content (quotes, control characters) reaches ~5.7×.
I expected the truncated response to fit within max_size.
One non-obvious detail in case it helps: the middleware decides whether to truncate using the serialized size (len(pydantic_core.to_json(result))), but after truncating it only bounds the text block — so the two sizes disagree.
Example Code
import asyncio
import pydantic_core
from fastmcp import FastMCP, Client
from fastmcp.server.middleware.response_limiting import ResponseLimitingMiddleware
MAX = 1000
async def check(label, payload):
mcp = FastMCP("t")
mcp.add_middleware(ResponseLimitingMiddleware(max_size=MAX))
@mcp.tool
def emit() -> str:
return payload
async with Client(mcp) as c:
r = await c.call_tool("emit", {})
# same measure the middleware uses to decide whether to truncate
size = len(pydantic_core.to_json(r, fallback=str))
print(f"{label:<20} serialized={size:>6} (max_size={MAX})")
async def main():
await check("plain ASCII", "A" * 10_000)
await check("control char", "\x01" * 10_000)
asyncio.run(main())
Output
plain ASCII serialized= 1187 (max_size=1000)
control char serialized= 5737 (max_size=1000)
Version Information
FastMCP version: 4.0.10
MCP version: 2.2.0
Python version: 3.10.21
Platform: Linux-6.8.0-124-generic-x86_64-with-glibc2.35
What happened?
With ResponseLimitingMiddleware(max_size=1000), responses over the limit get truncated, but the truncated response still serializes to more than max_size. A plain-ASCII response comes out at ~1.2× the limit; escape-heavy content (quotes, control characters) reaches ~5.7×.
I expected the truncated response to fit within max_size.
One non-obvious detail in case it helps: the middleware decides whether to truncate using the serialized size (len(pydantic_core.to_json(result))), but after truncating it only bounds the text block — so the two sizes disagree.
Example Code
Version Information