@@ -74,6 +74,13 @@ export type MCPTransportOptions = (
7474) & {
7575 authProvider ?: AgentsOAuthProvider ;
7676 type ?: TransportType ;
77+ /**
78+ * Connection timeout in milliseconds. Default: 15000 (15 seconds).
79+ * If the connection doesn't complete within this time, it will fail.
80+ * Timeouts are often caused by proxies (like Cloudflare WARP) that strip
81+ * SSE newline terminators, causing the EventSource parser to hang.
82+ */
83+ connectionTimeoutMs ?: number ;
7784} ;
7885
7986export type MCPClientConnectionResult = {
@@ -616,6 +623,8 @@ export class MCPClientConnection {
616623 ) : Promise < MCPClientConnectionResult > {
617624 const transports : BaseTransportType [ ] =
618625 transportType === "auto" ? [ "streamable-http" , "sse" ] : [ transportType ] ;
626+ const connectionTimeoutMs =
627+ this . options . transport ?. connectionTimeoutMs ?? 15000 ;
619628
620629 for ( const currentTransportType of transports ) {
621630 const isLastTransport =
@@ -628,7 +637,21 @@ export class MCPClientConnection {
628637 const transport = this . getTransport ( currentTransportType ) ;
629638
630639 try {
631- await this . client . connect ( transport ) ;
640+ // Timeouts are often caused by proxies (like Cloudflare WARP) that strip
641+ // SSE newline terminators (\n\n), causing the EventSource parser to hang
642+ // waiting for message boundaries that never arrive.
643+ await Promise . race ( [
644+ this . client . connect ( transport ) ,
645+ new Promise < never > ( ( _ , reject ) =>
646+ setTimeout (
647+ ( ) =>
648+ reject (
649+ new Error ( `Connection timeout after ${ connectionTimeoutMs } ms` )
650+ ) ,
651+ connectionTimeoutMs
652+ )
653+ )
654+ ] ) ;
632655
633656 return {
634657 state : MCPConnectionState . CONNECTED ,
0 commit comments