@@ -65,6 +65,16 @@ const BaseConfigSchema = z.object({
6565 disabledTools : z . array ( z . string ( ) ) . default ( [ ] ) ,
6666} )
6767
68+ // Certificate trust configuration schema
69+ const CertificateTrustSchema = z . object ( {
70+ // Allow self-signed certificates
71+ allowSelfSigned : z . boolean ( ) . optional ( ) ,
72+ // Path to CA certificate file (PEM format)
73+ caCertPath : z . string ( ) . optional ( ) ,
74+ // Reject unauthorized certificates (default: true for security)
75+ rejectUnauthorized : z . boolean ( ) . optional ( ) . default ( true ) ,
76+ } )
77+
6878// Custom error messages for better user feedback
6979const typeErrorMessage = "Server type must be 'stdio', 'sse', or 'streamable-http'"
7080const stdioFieldsErrorMessage =
@@ -102,6 +112,8 @@ const createServerTypeSchema = () => {
102112 type : z . enum ( [ "sse" ] ) . optional ( ) ,
103113 url : z . string ( ) . url ( "URL must be a valid URL format" ) ,
104114 headers : z . record ( z . string ( ) ) . optional ( ) ,
115+ // Certificate trust configuration for HTTPS connections
116+ certificateTrust : CertificateTrustSchema . optional ( ) ,
105117 // Ensure no stdio fields are present
106118 command : z . undefined ( ) . optional ( ) ,
107119 args : z . undefined ( ) . optional ( ) ,
@@ -117,6 +129,8 @@ const createServerTypeSchema = () => {
117129 type : z . enum ( [ "streamable-http" ] ) . optional ( ) ,
118130 url : z . string ( ) . url ( "URL must be a valid URL format" ) ,
119131 headers : z . record ( z . string ( ) ) . optional ( ) ,
132+ // Certificate trust configuration for HTTPS connections
133+ certificateTrust : CertificateTrustSchema . optional ( ) ,
120134 // Ensure no stdio fields are present
121135 command : z . undefined ( ) . optional ( ) ,
122136 args : z . undefined ( ) . optional ( ) ,
@@ -735,10 +749,47 @@ export class McpHub {
735749 }
736750 } else if ( configInjected . type === "streamable-http" ) {
737751 // Streamable HTTP connection
752+ const requestInit : RequestInit = {
753+ headers : configInjected . headers ,
754+ }
755+
756+ // Apply certificate trust settings if configured
757+ if ( configInjected . certificateTrust ) {
758+ const { allowSelfSigned, caCertPath, rejectUnauthorized } = configInjected . certificateTrust
759+
760+ // For Node.js fetch, we need to configure the agent
761+ if ( typeof process !== "undefined" && process . versions && process . versions . node ) {
762+ const https = await import ( "https" )
763+ const fs = await import ( "fs/promises" )
764+
765+ const agentOptions : any = { }
766+
767+ // Handle certificate rejection
768+ if ( rejectUnauthorized === false || allowSelfSigned === true ) {
769+ agentOptions . rejectUnauthorized = false
770+ }
771+
772+ // Load CA certificate if provided
773+ if ( caCertPath ) {
774+ try {
775+ const caCert = await fs . readFile ( caCertPath , "utf-8" )
776+ agentOptions . ca = caCert
777+ } catch ( error ) {
778+ console . error ( `Failed to load CA certificate from ${ caCertPath } :` , error )
779+ throw new Error (
780+ `Failed to load CA certificate: ${ error instanceof Error ? error . message : String ( error ) } ` ,
781+ )
782+ }
783+ }
784+
785+ // Create HTTPS agent with certificate trust settings
786+ const agent = new https . Agent ( agentOptions )
787+ ; ( requestInit as any ) . agent = agent
788+ }
789+ }
790+
738791 transport = new StreamableHTTPClientTransport ( new URL ( configInjected . url ) , {
739- requestInit : {
740- headers : configInjected . headers ,
741- } ,
792+ requestInit,
742793 } )
743794
744795 // Set up Streamable HTTP specific error handling
@@ -766,18 +817,66 @@ export class McpHub {
766817 headers : configInjected . headers ,
767818 } ,
768819 }
820+
769821 // Configure ReconnectingEventSource options
770- const reconnectingEventSourceOptions = {
822+ const reconnectingEventSourceOptions : any = {
771823 max_retry_time : 5000 , // Maximum retry time in milliseconds
772824 withCredentials : configInjected . headers ?. [ "Authorization" ] ? true : false , // Enable credentials if Authorization header exists
773- fetch : ( url : string | URL , init : RequestInit ) => {
825+ }
826+
827+ // Apply certificate trust settings if configured
828+ if ( configInjected . certificateTrust ) {
829+ const { allowSelfSigned, caCertPath, rejectUnauthorized } = configInjected . certificateTrust
830+
831+ // For Node.js fetch used by ReconnectingEventSource
832+ if ( typeof process !== "undefined" && process . versions && process . versions . node ) {
833+ const https = await import ( "https" )
834+ const fs = await import ( "fs/promises" )
835+
836+ const agentOptions : any = { }
837+
838+ // Handle certificate rejection
839+ if ( rejectUnauthorized === false || allowSelfSigned === true ) {
840+ agentOptions . rejectUnauthorized = false
841+ }
842+
843+ // Load CA certificate if provided
844+ if ( caCertPath ) {
845+ try {
846+ const caCert = await fs . readFile ( caCertPath , "utf-8" )
847+ agentOptions . ca = caCert
848+ } catch ( error ) {
849+ console . error ( `Failed to load CA certificate from ${ caCertPath } :` , error )
850+ throw new Error (
851+ `Failed to load CA certificate: ${ error instanceof Error ? error . message : String ( error ) } ` ,
852+ )
853+ }
854+ }
855+
856+ // Create HTTPS agent with certificate trust settings
857+ const agent = new https . Agent ( agentOptions )
858+
859+ // Custom fetch function that includes the HTTPS agent
860+ reconnectingEventSourceOptions . fetch = ( url : string | URL , init : RequestInit ) => {
861+ const headers = new Headers ( { ...( init ?. headers || { } ) , ...( configInjected . headers || { } ) } )
862+ return fetch ( url , {
863+ ...init ,
864+ headers,
865+ agent : agent as any ,
866+ } )
867+ }
868+ }
869+ } else {
870+ // Default fetch function without certificate trust modifications
871+ reconnectingEventSourceOptions . fetch = ( url : string | URL , init : RequestInit ) => {
774872 const headers = new Headers ( { ...( init ?. headers || { } ) , ...( configInjected . headers || { } ) } )
775873 return fetch ( url , {
776874 ...init ,
777875 headers,
778876 } )
779- } ,
877+ }
780878 }
879+
781880 global . EventSource = ReconnectingEventSource
782881 transport = new SSEClientTransport ( new URL ( configInjected . url ) , {
783882 ...sseOptions ,
0 commit comments