@@ -474,9 +474,12 @@ export abstract class Protocol<ContextT extends BaseContext> {
474474 } ) ;
475475
476476 this . setRequestHandler ( 'tasks/result' , async ( request , ctx ) => {
477- const handleTaskResult = async ( ) : Promise < Result > => {
478- const taskId = request . params . taskId ;
477+ const taskId = request . params . taskId ;
479478
479+ // Iterative poll loop: drain the queue and wait for the task to reach a terminal
480+ // state. Using an explicit loop (rather than recursion) avoids building up a
481+ // deep promise chain for long-running tasks.
482+ while ( true ) {
480483 // Deliver queued messages
481484 if ( this . _taskMessageQueue ) {
482485 let queuedMessage : QueuedMessage | undefined ;
@@ -528,15 +531,6 @@ export abstract class Protocol<ContextT extends BaseContext> {
528531 throw new ProtocolError ( ProtocolErrorCode . InvalidParams , `Task not found: ${ taskId } ` ) ;
529532 }
530533
531- // Block if task is not terminal (we've already delivered all queued messages above)
532- if ( ! isTerminal ( task . status ) ) {
533- // Wait for status change or new messages
534- await this . _waitForTaskUpdate ( taskId , ctx . mcpReq . signal ) ;
535-
536- // After waking up, recursively call to deliver any new messages or result
537- return await handleTaskResult ( ) ;
538- }
539-
540534 // If task is terminal, return the result
541535 if ( isTerminal ( task . status ) ) {
542536 const result = await this . _taskStore ! . getTaskResult ( taskId , ctx . sessionId ) ;
@@ -554,10 +548,9 @@ export abstract class Protocol<ContextT extends BaseContext> {
554548 } as Result ;
555549 }
556550
557- return await handleTaskResult ( ) ;
558- } ;
559-
560- return await handleTaskResult ( ) ;
551+ // Task is not yet terminal — wait for the next poll interval, then loop again
552+ await this . _waitForTaskUpdate ( taskId , ctx . mcpReq . signal ) ;
553+ }
561554 } ) ;
562555
563556 this . setRequestHandler ( 'tasks/list' , async ( request , ctx ) => {
0 commit comments