@@ -12,6 +12,7 @@ use mcpmux_core::{
1212 DomainEvent , FeatureSet , FeatureSetType , MemberMode , MemberType , ServerFeature ,
1313 WorkspaceBinding , WorkspaceRootValidation ,
1414} ;
15+ use mcpmux_storage:: InboundClientRepository ;
1516use serde:: { Deserialize , Serialize } ;
1617use tauri:: State ;
1718use tokio:: sync:: RwLock ;
@@ -23,6 +24,21 @@ use super::server_manager::ServerManagerState;
2324use super :: workspace_appearance:: maybe_remove_orphaned_icon_file;
2425use crate :: state:: AppState ;
2526
27+ fn inbound_client_repo ( state : & AppState ) -> InboundClientRepository {
28+ InboundClientRepository :: new ( state. database ( ) )
29+ }
30+
31+ /// Clear persisted prompt dismissals after a binding is saved for a root.
32+ async fn clear_binding_prompt_dismissals (
33+ state : & AppState ,
34+ workspace_root : & str ,
35+ ) -> Result < ( ) , String > {
36+ inbound_client_repo ( state)
37+ . clear_binding_prompt_dismissals_for_root ( workspace_root)
38+ . await
39+ . map_err ( |e| e. to_string ( ) )
40+ }
41+
2642/// Publish `WorkspaceBindingChanged` on the gateway's domain bus so
2743/// MCPNotifier broadcasts `list_changed` to every peer whose session now
2844/// routes through the changed binding.
@@ -429,6 +445,8 @@ pub async fn create_workspace_binding(
429445 . await
430446 . map_err ( |e| e. to_string ( ) ) ?;
431447
448+ clear_binding_prompt_dismissals ( & state, & binding. workspace_root ) . await ?;
449+
432450 if binding_type == BindingType :: Path {
433451 clear_appearance_for_bound_root ( & state, & normalized) . await ?;
434452 }
@@ -533,6 +551,8 @@ pub async fn update_workspace_binding(
533551 . await
534552 . map_err ( |e| e. to_string ( ) ) ?;
535553
554+ clear_binding_prompt_dismissals ( & state, & updated. workspace_root ) . await ?;
555+
536556 if binding_type == BindingType :: Path {
537557 clear_appearance_for_bound_root ( & state, & normalized) . await ?;
538558 }
@@ -561,6 +581,40 @@ pub async fn update_workspace_binding(
561581 Ok ( updated. into ( ) )
562582}
563583
584+ /// Record that the user closed the WorkspaceNeedsBinding panel without saving.
585+ #[ tauri:: command]
586+ pub async fn dismiss_workspace_binding_prompt (
587+ client_id : String ,
588+ workspace_root : String ,
589+ state : State < ' _ , AppState > ,
590+ ) -> Result < ( ) , String > {
591+ inbound_client_repo ( & state)
592+ . dismiss_binding_prompt ( & client_id, & workspace_root)
593+ . await
594+ . map_err ( |e| e. to_string ( ) )
595+ }
596+
597+ /// Whether the binding prompt was dismissed for a client/root pair, or — when
598+ /// `client_id` is omitted — for any client on that workspace root.
599+ #[ tauri:: command]
600+ pub async fn is_workspace_binding_prompt_dismissed (
601+ workspace_root : String ,
602+ client_id : Option < String > ,
603+ state : State < ' _ , AppState > ,
604+ ) -> Result < bool , String > {
605+ let repo = inbound_client_repo ( & state) ;
606+ match client_id {
607+ Some ( cid) if !cid. is_empty ( ) => repo
608+ . is_binding_prompt_dismissed ( & cid, & workspace_root)
609+ . await
610+ . map_err ( |e| e. to_string ( ) ) ,
611+ _ => repo
612+ . is_binding_prompt_dismissed_for_root ( & workspace_root)
613+ . await
614+ . map_err ( |e| e. to_string ( ) ) ,
615+ }
616+ }
617+
564618/// Delete a binding by id.
565619#[ tauri:: command]
566620pub async fn delete_workspace_binding (
0 commit comments