Apply the request body limit to the SSE and OAuth endpoints

Merged
MA
2mo ago
+420-189

#3095 added RequestBodyLimitMiddleware and applied it to the Streamable HTTP endpoint. This does the same for the other two places that accept request bodies, so every HTTP entry point shares the one 4 MiB default.

Motivation and Context

  • SseServerTransport takes max_request_body_size (default 4 MiB, same validation as StreamableHTTPSessionManager), and MCPServer.sse_app() / run(transport="sse") pass it through, mirroring streamable_http_app(). The message endpoint now answers 405 to anything that isn't a POST instead of treating it as one.
  • The create_auth_routes endpoints (/token, /revoke, /register, POST /authorize) use the default limit. On the CORS-enabled routes it sits inside the CORS wrapper, so a 413 still carries CORS headers and preflights are untouched. These endpoints use the 4 MiB default rather than a configurable value; their payloads are a few kilobytes.
  • The middleware itself no longer special-cases POST: the limit applies to a request body whatever method carries it, since some of these routes also accept OPTIONS/HEAD and their handlers read the body either way.
  • RequestBodyLimitMiddleware and DEFAULT_MAX_REQUEST_BODY_SIZE move to mcp.server.transport_security, next to the other shared HTTP request checks, now that three modules use them. Both remain importable from mcp.server.streamable_http_manager.

Nothing changes for requests under the limit.

How Has This Been Tested?

New tests in tests/server/test_sse_security.py, tests/server/auth/test_error_handling.py, tests/server/test_transport_security.py and tests/server/mcpserver/test_server.py: over-limit bodies (declared and streamed, across methods) get 413, bodies under the limit still reach session lookup / form parsing, CORS preflights are still answered and a 413 on a CORS route keeps its CORS headers, non-POST to the message endpoint gets 405, and sse_app() applies the configured value. Full suite, pyright and ruff pass locally.

Breaking Changes

None. The new keyword is optional and defaults to the limit streamable_http_app() already uses; the observable differences are a 413 for request bodies over 4 MiB on these endpoints and a 405 for non-POST requests to the SSE message endpoint.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I am assigned to the linked issue (or it is labeled help wanted, or I'm a maintainer)
  • I have disclosed any AI assistance and can explain the change in my own words
  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

docs/run/index.md describes max_request_body_size as the largest accepted request body; no new documentation for the SSE transport.

AI Disclaimer