Skip to content

server: add max_body_bytes guard for HTTP request bodies#2012

Open
TheodorNEngoy wants to merge 6 commits intomodelcontextprotocol:mainfrom
TheodorNEngoy:codex/max-body-bytes
Open

server: add max_body_bytes guard for HTTP request bodies#2012
TheodorNEngoy wants to merge 6 commits intomodelcontextprotocol:mainfrom
TheodorNEngoy:codex/max-body-bytes

Conversation

@TheodorNEngoy
Copy link

@TheodorNEngoy TheodorNEngoy commented Feb 7, 2026

Adds a configurable request-body size cap to avoid unbounded await request.body() buffering for MCP HTTP endpoints.

Changes:

  • Add max_body_bytes (default: 1_000_000, None disables) to:
    • StreamableHTTPServerTransport
    • StreamableHTTPSessionManager + Server.streamable_http_app() plumbing
    • MCPServer.streamable_http_app() / MCPServer.run(..., transport='streamable-http') passthrough
    • SseServerTransport
    • MCPServer.sse_app() / MCPServer.run(..., transport='sse') passthrough
    • OAuth dynamic client registration /register handler via ClientRegistrationOptions.max_body_bytes
  • Enforce the limit while reading the body (streaming) and return 413 Payload Too Large (with Connection: close) when exceeded.
  • Add tests covering StreamableHTTP, SSE, and /register.
  • Add README notes about the default limit + how to override.

Local checks:

  • uv run ruff check src tests
  • uv run pyright
  • uv run pytest -q tests/server/test_streamable_http_manager.py tests/server/test_sse_max_body_bytes.py tests/server/auth/test_error_handling.py

@TheodorNEngoy
Copy link
Author

Pushed a follow-up to fix CI:

  • end-of-file fixer issue in http_body.py
  • added focused tests to cover max_body_bytes edge cases + transport validation
  • adjusted one test for pyright (typed Any)

Coverage now reports 100% locally (matches CI settings), so checks should go green on the next run.

@TheodorNEngoy
Copy link
Author

Clarifying my previous comment (shell ate the backticks):

  • Removed a few incorrect '# pragma: no cover' markers so strict-no-cover passes.
  • Expanded SSE tests so the CI fail_under=100 coverage gate stays green.

@TheodorNEngoy
Copy link
Author

Follow-up (CI): windows py3.12 locked was failing in TestChildProcessCleanup.test_nested_process_tree due to a timing-sensitive “file grew after 0.3s” assertion and then leaking subprocesses on failure.

I updated that test to poll briefly for file growth and to always terminate the process tree in finally, which should make that job reliable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant