@@ -176,6 +176,9 @@ type HttpModeT =
176
176
| { value : HttpMode . Http ; sessionId : string | undefined }
177
177
| { value : HttpMode . SSE ; endpoint : string } ;
178
178
179
+ const MAX_FOLLOW_REDIRECTS = 5 ;
180
+ const REDIRECT_STATUS_CODES = [ 301 , 302 , 303 , 307 , 308 ] ;
181
+
179
182
/**
180
183
* Implementation of both MCP HTTP Streaming as well as legacy SSE.
181
184
*
@@ -702,21 +705,46 @@ class McpHTTPHandle extends Disposable {
702
705
}
703
706
this . _log ( LogLevel . Trace , `Fetching ${ url } with options: ${ JSON . stringify ( traceObj ) } ` ) ;
704
707
}
705
- const res = await fetch ( url , {
706
- ...init ,
707
- signal : this . _abortCtrl . signal ,
708
- } ) ;
708
+
709
+ let currentUrl = url ;
710
+ let response ! : Response ;
711
+ for ( let redirectCount = 0 ; redirectCount < MAX_FOLLOW_REDIRECTS ; redirectCount ++ ) {
712
+ response = await fetch ( currentUrl , {
713
+ ...init ,
714
+ signal : this . _abortCtrl . signal ,
715
+ redirect : 'manual'
716
+ } ) ;
717
+
718
+ // Check for redirect status codes (301, 302, 303, 307, 308)
719
+ if ( ! REDIRECT_STATUS_CODES . includes ( response . status ) ) {
720
+ break ;
721
+ }
722
+
723
+ const location = response . headers . get ( 'location' ) ;
724
+ if ( ! location ) {
725
+ break ;
726
+ }
727
+
728
+ const nextUrl = new URL ( location , currentUrl ) . toString ( ) ;
729
+ this . _log ( LogLevel . Trace , `Redirect (${ response . status } ) from ${ currentUrl } to ${ nextUrl } ` ) ;
730
+ currentUrl = nextUrl ;
731
+ // Per fetch spec, for 303 always use GET, keep method unless original was POST and 301/302, then GET.
732
+ if ( response . status === 303 || ( ( response . status === 301 || response . status === 302 ) && init . method === 'POST' ) ) {
733
+ init . method = 'GET' ;
734
+ delete init . body ;
735
+ }
736
+ }
709
737
710
738
if ( canLog ( this . _logService . getLevel ( ) , LogLevel . Trace ) ) {
711
739
const headers : Record < string , string > = { } ;
712
- res . headers . forEach ( ( value , key ) => { headers [ key ] = value ; } ) ;
713
- this . _log ( LogLevel . Trace , `Fetched ${ url } : ${ JSON . stringify ( {
714
- status : res . status ,
740
+ response . headers . forEach ( ( value , key ) => { headers [ key ] = value ; } ) ;
741
+ this . _log ( LogLevel . Trace , `Fetched ${ currentUrl } : ${ JSON . stringify ( {
742
+ status : response . status ,
715
743
headers : headers ,
716
744
} ) } `) ;
717
745
}
718
746
719
- return res ;
747
+ return response ;
720
748
}
721
749
}
722
750
0 commit comments