Repository navigation
Conversation
The streamable-HTTP transport reads each request body whole into memory before parsing it as JSON-RPC, and axum's default extractor limit never reaches it (the transport is a tower service, not an extractor), so the hosted /mcp route had no bound on what one request could make the process buffer. Caddy in front sets a read timeout but no size cap. A middleware layer inside the bearer gate now refuses a body over the cap with 413: a declared Content-Length over it is refused unread, and an undeclared (chunked) body is read up to the cap and no further. The gate still answers an unauthenticated request on its headers alone, so only an authenticated caller's body is read at all. Default 4 MiB (an IC ingress message is at most 2 MiB, so any one canister call fits even spelled out as JSON); embedders set it with McpServer::with_max_request_body, the binary from $MCP_MAX_REQUEST_BODY. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The hosted
/mcproute gets a cap on the request body, enforced behind the bearer gate.Why
rmcp's streamable-HTTP service collects each request body whole before parsing it as JSON-RPC (
expect_jsoninserver_side_http.rs), and because it is a tower service rather than an axum extractor, axum's default 2 MiB extractor limit never applies to it. There was no body-limit layer on the route and Caddy sets only a read timeout, so any bearer-token holder could make the process buffer a body of arbitrary size. The staging unit runs underMemoryMax=2G.This is independent of the deploy stack (#230–#232), but the hosted deploy work that follows will need a deploy-aware exemption from a general cap, so the general cap comes first and on its own.
How
src/body_limit.rs: a middleware that refuses a body over the cap with413. A declaredContent-Lengthover the cap is refused without reading the body; an undeclared (chunked) body is read up to the cap and no further (axum::body::to_byteswith the limit, tellingLengthLimitErrorfrom a transport error). A body within the cap is handed on whole, which the transport buffers anyway.require_token, then the cap. An unauthenticated request is still answered on its headers alone with the401challenge, so only an authenticated caller's body is read at all.DEFAULT_MAX_REQUEST_BODY= 4 MiB. An IC ingress message is at most 2 MiB, so any single canister call fits even when its argument is spelled out as JSON. Embedders override withMcpServer::with_max_request_body(bytes)(a setter, soMcpConfigkeeps its shape for the published crate's embedders); the binary reads$MCP_MAX_REQUEST_BODYand refuses to start on a value that is not a byte count.AuthStore::test_beareris acfg(test)helper that mints a token without an II handshake.http-body-utilmoves from dev-dependencies to dependencies forLengthLimitError;futures-utilis added as a dev-dependency for streamed test bodies. Both were already in the tree.🤖 Generated with Claude Code