@@ -3,6 +3,7 @@ package http
33import (
44 "context"
55 "encoding/json"
6+ "fmt"
67 "log/slog"
78 "net/http"
89 "net/http/httptest"
@@ -1288,11 +1289,23 @@ func TestUIMetaStrippedWhenClientLacksCapability(t *testing.T) {
12881289 require .NotNil (t , unknown [0 ].Tool .Meta ["ui" ], "_meta.ui should be preserved when capability is unknown and FF is on" )
12891290}
12901291
1291- // TestRegisterMiddleware_MaxRequestBodySize verifies that RegisterMiddleware
1292- // wires the body-size limit ahead of the body-consuming middleware, so an
1293- // oversized request never reaches the MCP server, and that requests within
1294- // the configured limit (including exactly at the boundary) still succeed.
1295- func TestRegisterMiddleware_MaxRequestBodySize (t * testing.T ) {
1292+ // TestMaxRequestBodyBytes checks the effective limit tracks the MCP SDK
1293+ // default and honours an operator override.
1294+ func TestMaxRequestBodyBytes (t * testing.T ) {
1295+ t .Run ("defaults to the MCP SDK limit" , func (t * testing.T ) {
1296+ h := & Handler {config : & ServerConfig {}}
1297+ assert .Equal (t , int64 (mcp .DefaultMaxRequestBodyBytes ), h .maxRequestBodyBytes ())
1298+ })
1299+
1300+ t .Run ("configured value overrides the default" , func (t * testing.T ) {
1301+ h := & Handler {config : & ServerConfig {MaxRequestBodyBytes : 1234 }}
1302+ assert .Equal (t , int64 (1234 ), h .maxRequestBodyBytes ())
1303+ })
1304+ }
1305+
1306+ // TestMaxRequestBodySizeEnforcement exercises both layers the limit is applied
1307+ // at: the early middleware, and the MCP SDK handler the request is delegated to.
1308+ func TestMaxRequestBodySizeEnforcement (t * testing.T ) {
12961309 const limit = 256
12971310
12981311 apiHost , err := utils .NewAPIHost ("https://api.github.com" )
@@ -1307,9 +1320,9 @@ func TestRegisterMiddleware_MaxRequestBodySize(t *testing.T) {
13071320 return strings .Replace (payload , "PADDING" , "PADDING" + pad , 1 )
13081321 }
13091322
1310- newHandler := func (t * testing.T , mcpServerFactoryCalled * bool ) http. Handler {
1323+ newHandler := func (t * testing.T , mcpServerFactoryCalled * bool ) * Handler {
13111324 t .Helper ()
1312- handler := NewHTTPMcpHandler (
1325+ return NewHTTPMcpHandler (
13131326 context .Background (),
13141327 & ServerConfig {Version : "test" , MaxRequestBodyBytes : limit },
13151328 nil ,
@@ -1327,47 +1340,63 @@ func TestRegisterMiddleware_MaxRequestBodySize(t *testing.T) {
13271340 }),
13281341 WithScopeFetcher (allScopesFetcher {}),
13291342 )
1343+ }
13301344
1345+ newRouter := func (h * Handler ) http.Handler {
13311346 r := chi .NewRouter ()
1332- handler .RegisterMiddleware (r )
1333- handler .RegisterRoutes (r )
1347+ h .RegisterMiddleware (r )
1348+ h .RegisterRoutes (r )
13341349 return r
13351350 }
13361351
1337- t .Run ("oversized request is rejected before reaching the MCP server" , func (t * testing.T ) {
1352+ newRequest := func (body string ) * http.Request {
1353+ req := httptest .NewRequest (http .MethodPost , "/" , strings .NewReader (body ))
1354+ req .Header .Set (headers .ContentTypeHeader , headers .ContentTypeJSON )
1355+ req .Header .Set (headers .AcceptHeader , strings .Join ([]string {headers .ContentTypeJSON , headers .ContentTypeEventStream }, ", " ))
1356+ req .Header .Set (headers .AuthorizationHeader , strings .Join ([]string {"ghs" , "test-token" }, "_" ))
1357+ return req
1358+ }
1359+
1360+ t .Run ("middleware rejects an oversized request before the MCP server is built" , func (t * testing.T ) {
13381361 var mcpServerFactoryCalled bool
1339- r := newHandler (t , & mcpServerFactoryCalled )
1362+ r := newRouter ( newHandler (t , & mcpServerFactoryCalled ) )
13401363
13411364 body := buildBody (limit + 1 )
13421365 require .Greater (t , len (body ), limit )
13431366
1344- req := httptest .NewRequest (http .MethodPost , "/" , strings .NewReader (body ))
1345- req .Header .Set (headers .AuthorizationHeader , strings .Join ([]string {"ghs" , "test-token" }, "_" ))
1346-
13471367 rr := httptest .NewRecorder ()
1348- r .ServeHTTP (rr , req )
1368+ r .ServeHTTP (rr , newRequest ( body ) )
13491369
13501370 assert .Equal (t , http .StatusRequestEntityTooLarge , rr .Code )
13511371 assert .Contains (t , rr .Body .String (), "request body too large" )
13521372 assert .False (t , mcpServerFactoryCalled , "the MCP server should never be constructed for an oversized request" )
13531373 })
13541374
1355- t .Run ("boundary-size request at the configured limit succeeds" , func (t * testing.T ) {
1375+ t .Run ("request at the configured limit succeeds" , func (t * testing.T ) {
13561376 var mcpServerFactoryCalled bool
1357- r := newHandler (t , & mcpServerFactoryCalled )
1377+ r := newRouter ( newHandler (t , & mcpServerFactoryCalled ) )
13581378
13591379 body := buildBody (limit )
13601380 require .Len (t , body , limit )
13611381
1362- req := httptest .NewRequest (http .MethodPost , "/" , strings .NewReader (body ))
1363- req .Header .Set (headers .ContentTypeHeader , headers .ContentTypeJSON )
1364- req .Header .Set (headers .AcceptHeader , strings .Join ([]string {headers .ContentTypeJSON , headers .ContentTypeEventStream }, ", " ))
1365- req .Header .Set (headers .AuthorizationHeader , strings .Join ([]string {"ghs" , "test-token" }, "_" ))
1366-
13671382 rr := httptest .NewRecorder ()
1368- r .ServeHTTP (rr , req )
1383+ r .ServeHTTP (rr , newRequest ( body ) )
13691384
13701385 assert .Equal (t , http .StatusOK , rr .Code , "response body: %s" , rr .Body .String ())
13711386 assert .True (t , mcpServerFactoryCalled , "the MCP server should be constructed for an allowed request" )
13721387 })
1388+
1389+ t .Run ("SDK handler enforces the configured limit when the middleware is bypassed" , func (t * testing.T ) {
1390+ h := newHandler (t , nil )
1391+
1392+ body := buildBody (limit + 1 )
1393+ require .Greater (t , len (body ), limit )
1394+
1395+ rr := httptest .NewRecorder ()
1396+ h .ServeHTTP (rr , newRequest (body ))
1397+
1398+ assert .Equal (t , http .StatusRequestEntityTooLarge , rr .Code )
1399+ assert .Contains (t , rr .Body .String (), fmt .Sprintf ("request body exceeds %d bytes" , limit ),
1400+ "the SDK should report the configured limit, not its own default" )
1401+ })
13731402}
0 commit comments