@@ -960,3 +960,109 @@ func TestDeviceCode_VerificationPage(t *testing.T) {
960960 assert .Contains (t , string (body ), "Device Verification" )
961961 assert .Contains (t , string (body ), deviceResp .UserCode ) // Should pre-fill the user code
962962}
963+
964+ // --- MCP Rate Limiting Tests ---
965+
966+ func TestMCPRateLimiting (t * testing.T ) {
967+ t .Run ("returns 429 with Retry-After header" , func (t * testing.T ) {
968+ server := Start (t , Options {
969+ ErrorMode : ErrorMode {
970+ MCPRateLimitCount : 2 ,
971+ MCPRateLimitRetryAfter : 5 ,
972+ },
973+ })
974+ defer server .Shutdown ()
975+
976+ client := & http.Client {}
977+
978+ // First request should return 429
979+ resp1 , err := client .Post (server .MCPURL , "application/json" , strings .NewReader ("{}" ))
980+ require .NoError (t , err )
981+ defer resp1 .Body .Close ()
982+ assert .Equal (t , http .StatusTooManyRequests , resp1 .StatusCode )
983+ assert .Equal (t , "5" , resp1 .Header .Get ("Retry-After" ))
984+
985+ // Second request should also return 429
986+ resp2 , err := client .Post (server .MCPURL , "application/json" , strings .NewReader ("{}" ))
987+ require .NoError (t , err )
988+ defer resp2 .Body .Close ()
989+ assert .Equal (t , http .StatusTooManyRequests , resp2 .StatusCode )
990+
991+ // Third request should return 401 (past rate limit count)
992+ resp3 , err := client .Post (server .MCPURL , "application/json" , strings .NewReader ("{}" ))
993+ require .NoError (t , err )
994+ defer resp3 .Body .Close ()
995+ assert .Equal (t , http .StatusUnauthorized , resp3 .StatusCode )
996+ assert .Contains (t , resp3 .Header .Get ("WWW-Authenticate" ), "resource_metadata" )
997+ })
998+
999+ t .Run ("returns 429 with reset_at in body" , func (t * testing.T ) {
1000+ server := Start (t , Options {
1001+ ErrorMode : ErrorMode {
1002+ MCPRateLimitCount : 1 ,
1003+ MCPRateLimitRetryAfter : 10 ,
1004+ MCPRateLimitUseResetAt : true ,
1005+ },
1006+ })
1007+ defer server .Shutdown ()
1008+
1009+ client := & http.Client {}
1010+
1011+ resp , err := client .Post (server .MCPURL , "application/json" , strings .NewReader ("{}" ))
1012+ require .NoError (t , err )
1013+ defer resp .Body .Close ()
1014+
1015+ assert .Equal (t , http .StatusTooManyRequests , resp .StatusCode )
1016+ assert .Empty (t , resp .Header .Get ("Retry-After" ), "Should not have Retry-After header when using reset_at" )
1017+
1018+ body , _ := io .ReadAll (resp .Body )
1019+ assert .Contains (t , string (body ), "reset_at" )
1020+ })
1021+
1022+ t .Run ("ResetRateLimitCounter works" , func (t * testing.T ) {
1023+ server := Start (t , Options {
1024+ ErrorMode : ErrorMode {
1025+ MCPRateLimitCount : 1 ,
1026+ MCPRateLimitRetryAfter : 1 ,
1027+ },
1028+ })
1029+ defer server .Shutdown ()
1030+
1031+ client := & http.Client {}
1032+
1033+ // First request returns 429
1034+ resp1 , _ := client .Post (server .MCPURL , "application/json" , strings .NewReader ("{}" ))
1035+ resp1 .Body .Close ()
1036+ assert .Equal (t , http .StatusTooManyRequests , resp1 .StatusCode )
1037+
1038+ // Reset counter
1039+ server .Server .ResetRateLimitCounter ()
1040+
1041+ // Next request should return 429 again (counter reset)
1042+ resp2 , _ := client .Post (server .MCPURL , "application/json" , strings .NewReader ("{}" ))
1043+ resp2 .Body .Close ()
1044+ assert .Equal (t , http .StatusTooManyRequests , resp2 .StatusCode )
1045+ })
1046+ }
1047+
1048+ // --- Protected Resource Metadata Tests ---
1049+
1050+ func TestProtectedResourceMetadata (t * testing.T ) {
1051+ server := Start (t , Options {})
1052+ defer server .Shutdown ()
1053+
1054+ resp , err := http .Get (server .ProtectedResourceMetadataURL )
1055+ require .NoError (t , err )
1056+ defer resp .Body .Close ()
1057+
1058+ assert .Equal (t , http .StatusOK , resp .StatusCode )
1059+ assert .Equal (t , "application/json" , resp .Header .Get ("Content-Type" ))
1060+
1061+ var metadata map [string ]interface {}
1062+ err = json .NewDecoder (resp .Body ).Decode (& metadata )
1063+ require .NoError (t , err )
1064+
1065+ assert .Equal (t , server .MCPURL , metadata ["resource" ])
1066+ assert .Contains (t , metadata , "authorization_servers" )
1067+ assert .Contains (t , metadata , "scopes_supported" )
1068+ }
0 commit comments