diff --git a/crates/tui/src/lib.rs b/crates/tui/src/lib.rs index 5951a05ca3..924733a10d 100644 --- a/crates/tui/src/lib.rs +++ b/crates/tui/src/lib.rs @@ -1527,7 +1527,8 @@ enum McpCommand { #[arg(long, default_value_t = false)] force: bool, }, - /// Connect to MCP servers and report status + /// Connect to MCP servers and report status (does not attach to a + /// running session) Connect { /// Optional server name to connect to #[arg(value_name = "SERVER")] @@ -11201,6 +11202,40 @@ fn mcp_server_listing(command: Option<&str>, args: &[String], url: Option<&str>) } } +/// Printed after `mcp connect` and `mcp validate` succeed. docs/MCP.md +/// ยง Connection Lifecycle already states that these commands inspect their +/// own process's pool and never attach transports to a running TUI or exec +/// session; the success line alone reads as a real fix for the running +/// session otherwise (issue #6828). +const MCP_OWN_PROCESS_NOTE: [&str; 2] = [ + "Note: this command ran in its own process; it does not attach to a running TUI or exec session.", + "In a running session, use in-session discovery: search for the server name or an mcp__ tool name, or call one of its tools directly.", +]; + +fn print_mcp_own_process_note() { + for line in MCP_OWN_PROCESS_NOTE { + println!("{line}"); + } +} + +#[cfg(test)] +mod mcp_own_process_note_tests { + use super::MCP_OWN_PROCESS_NOTE; + + #[test] + fn mcp_own_process_note_states_the_session_boundary_and_recovery() { + let note = MCP_OWN_PROCESS_NOTE.join("\n"); + assert!( + note.contains("own process") && note.contains("does not attach"), + "the connect/validate note must name the process boundary: {note}" + ); + assert!( + note.contains("search for the server name"), + "the note must point at in-session discovery: {note}" + ); + } +} + async fn run_mcp_command( config: &Config, workspace: &Path, @@ -11299,10 +11334,12 @@ async fn run_mcp_command( return Err(err); } println!("Connected to MCP server: {name}"); + print_mcp_own_process_note(); } else { let errors = pool.connect_all().await; if errors.is_empty() { println!("Connected to all configured MCP servers."); + print_mcp_own_process_note(); } else { for (name, err) in errors { eprintln!("Failed to connect {name}: {err:#}"); @@ -11507,6 +11544,7 @@ async fn run_mcp_command( let errors = pool.connect_all().await; if errors.is_empty() { println!("MCP config is valid. All enabled servers connected."); + print_mcp_own_process_note(); return Ok(()); } eprintln!("MCP validation failed:");