@@ -37,6 +37,11 @@ export type ProtocolOptions = {
3737 enforceStrictCapabilities ?: boolean ;
3838} ;
3939
40+ /**
41+ * The default request timeout, in miliseconds.
42+ */
43+ export const DEFAULT_REQUEST_TIMEOUT_MSEC = 60000 ;
44+
4045/**
4146 * Options that can be given per request.
4247 */
@@ -50,6 +55,13 @@ export type RequestOptions = {
5055 * Can be used to cancel an in-flight request. This will cause an AbortError to be raised from request().
5156 */
5257 signal ?: AbortSignal ;
58+
59+ /**
60+ * A timeout (in milliseconds) for this request. If exceeded, an McpError with code `RequestTimeout` will be raised from request().
61+ *
62+ * If not specified, `DEFAULT_REQUEST_TIMEOUT_MSEC` will be used as the timeout.
63+ */
64+ timeout ?: number ;
5365} ;
5466
5567/**
@@ -379,7 +391,13 @@ export abstract class Protocol<
379391 } ;
380392 }
381393
394+ let timeoutId : ReturnType < typeof setTimeout > | undefined = undefined ;
395+
382396 this . _responseHandlers . set ( messageId , ( response ) => {
397+ if ( timeoutId !== undefined ) {
398+ clearTimeout ( timeoutId ) ;
399+ }
400+
383401 if ( options ?. signal ?. aborted ) {
384402 return ;
385403 }
@@ -396,8 +414,7 @@ export abstract class Protocol<
396414 }
397415 } ) ;
398416
399- options ?. signal ?. addEventListener ( "abort" , ( ) => {
400- const reason = options ?. signal ?. reason ;
417+ const cancel = ( reason : unknown ) => {
401418 this . _responseHandlers . delete ( messageId ) ;
402419 this . _progressHandlers . delete ( messageId ) ;
403420
@@ -411,9 +428,34 @@ export abstract class Protocol<
411428 } ) ;
412429
413430 reject ( reason ) ;
431+ } ;
432+
433+ options ?. signal ?. addEventListener ( "abort" , ( ) => {
434+ if ( timeoutId !== undefined ) {
435+ clearTimeout ( timeoutId ) ;
436+ }
437+
438+ cancel ( options ?. signal ?. reason ) ;
414439 } ) ;
415440
416- this . _transport . send ( jsonrpcRequest ) . catch ( reject ) ;
441+ const timeout = options ?. timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC ;
442+ timeoutId = setTimeout (
443+ ( ) =>
444+ cancel (
445+ new McpError ( ErrorCode . RequestTimeout , "Request timed out" , {
446+ timeout,
447+ } ) ,
448+ ) ,
449+ timeout ,
450+ ) ;
451+
452+ this . _transport . send ( jsonrpcRequest ) . catch ( ( error ) => {
453+ if ( timeoutId !== undefined ) {
454+ clearTimeout ( timeoutId ) ;
455+ }
456+
457+ reject ( error ) ;
458+ } ) ;
417459 } ) ;
418460 }
419461
0 commit comments