@@ -47,6 +47,7 @@ use tokio::sync::{
4747use tokio:: task:: JoinHandle ;
4848use tracing:: {
4949 error,
50+ info,
5051 warn,
5152} ;
5253
@@ -527,7 +528,18 @@ impl ToolManagerBuilder {
527528 // request method on the mcp client no longer buffers all the pages from
528529 // list calls.
529530 match msg {
530- UpdateEventMessage :: ToolsListResult { server_name, result } => {
531+ UpdateEventMessage :: ToolsListResult {
532+ server_name,
533+ result,
534+ pid,
535+ } => {
536+ let pid = pid. unwrap ( ) ;
537+ if !is_process_running ( pid) {
538+ info ! (
539+ "Received tool list result from {server_name} but its associated process {pid} is no longer running. Ignoring."
540+ ) ;
541+ return ;
542+ }
531543 let time_taken =
532544 loading_servers
533545 . remove ( & server_name)
@@ -708,9 +720,19 @@ impl ToolManagerBuilder {
708720 }
709721 }
710722 } ,
711- UpdateEventMessage :: PromptsListResult { server_name, result } => match result {
712- Ok ( prompt_list_result) => {
713- tracing:: error!( "## swap: received prompts from {server_name}" ) ;
723+ UpdateEventMessage :: PromptsListResult {
724+ server_name,
725+ result,
726+ pid,
727+ } => match result {
728+ Ok ( prompt_list_result) if pid. is_some ( ) => {
729+ let pid = pid. unwrap ( ) ;
730+ if !is_process_running ( pid) {
731+ info ! (
732+ "Received prompt list result from {server_name} but its associated process {pid} is no longer running. Ignoring."
733+ ) ;
734+ return ;
735+ }
714736 // We first need to clear all the PromptGets that are associated with
715737 // this server because PromptsListResult is declaring what is available
716738 // (and not the diff)
@@ -740,6 +762,9 @@ impl ToolManagerBuilder {
740762 } ) ;
741763 }
742764 } ,
765+ Ok ( _) => {
766+ error ! ( "Received prompt list result without pid from {server_name}. Ignoring." ) ;
767+ } ,
743768 Err ( e) => {
744769 error ! ( "Error fetching prompts from server {server_name}: {:?}" , e) ;
745770 let mut buf_writer = BufWriter :: new ( & mut * record_temp_buf) ;
@@ -761,16 +786,18 @@ impl ToolManagerBuilder {
761786 UpdateEventMessage :: ResourcesListResult {
762787 server_name : _,
763788 result : _,
789+ pid : _,
764790 } => { } ,
765791 UpdateEventMessage :: ResourceTemplatesListResult {
766792 server_name : _,
767793 result : _,
794+ pid : _,
768795 } => { } ,
769- UpdateEventMessage :: InitStart { server_name } => {
796+ UpdateEventMessage :: InitStart { server_name, .. } => {
770797 pending_clone. write ( ) . await . insert ( server_name. clone ( ) ) ;
771798 loading_servers. insert ( server_name, std:: time:: Instant :: now ( ) ) ;
772799 } ,
773- UpdateEventMessage :: Deinit { server_name } => {
800+ UpdateEventMessage :: Deinit { server_name, .. } => {
774801 // Only prompts are stored here so we'll just be clearing that
775802 // In the future if we are also storing tools, we need to make sure that
776803 // the tools are also pruned.
@@ -821,9 +848,11 @@ impl ToolManagerBuilder {
821848 debug_assert ! ( messenger_builder. is_some( ) ) ;
822849 let messenger_builder = messenger_builder. unwrap ( ) ;
823850 for ( mut name, init_res) in pre_initialized {
824- let messenger = messenger_builder. build_with_name ( name. clone ( ) ) ;
851+ let mut messenger = messenger_builder. build_with_name ( name. clone ( ) ) ;
825852 match init_res {
826853 Ok ( mut client) => {
854+ let pid = client. get_pid ( ) ;
855+ messenger. pid = pid;
827856 client. assign_messenger ( Box :: new ( messenger) ) ;
828857 let mut client = Arc :: new ( client) ;
829858 while let Some ( collided_client) = clients. insert ( name. clone ( ) , client) {
@@ -1611,6 +1640,39 @@ fn sanitize_name(orig: String, regex: ®ex::Regex, hasher: &mut impl Hasher) -
16111640 }
16121641}
16131642
1643+ // Add this function to check if a process is still running
1644+ fn is_process_running ( pid : u32 ) -> bool {
1645+ #[ cfg( unix) ]
1646+ {
1647+ // On Unix systems, we can use kill with signal 0 to check if process exists
1648+ std:: process:: Command :: new ( "ps" )
1649+ . arg ( "-p" )
1650+ . arg ( pid. to_string ( ) )
1651+ . output ( )
1652+ . map ( |output| output. status . success ( ) )
1653+ . unwrap_or ( false )
1654+ }
1655+ #[ cfg( windows) ]
1656+ {
1657+ // On Windows, try to open the process handle
1658+ use std:: ptr;
1659+
1660+ use winapi:: um:: handleapi:: CloseHandle ;
1661+ use winapi:: um:: processthreadsapi:: OpenProcess ;
1662+ use winapi:: um:: winnt:: PROCESS_QUERY_INFORMATION ;
1663+
1664+ unsafe {
1665+ let handle = OpenProcess ( PROCESS_QUERY_INFORMATION , 0 , pid) ;
1666+ if handle != ptr:: null_mut ( ) {
1667+ CloseHandle ( handle) ;
1668+ true
1669+ } else {
1670+ false
1671+ }
1672+ }
1673+ }
1674+ }
1675+
16141676fn queue_success_message ( name : & str , time_taken : & str , output : & mut impl Write ) -> eyre:: Result < ( ) > {
16151677 Ok ( queue ! (
16161678 output,
0 commit comments