Skip to content

Commit 9dd4f27

Browse files
authored
fix: mcp loading status (#1919)
* precomputes total number of servers in loading prior to spawning display task * changes display task to use async task instead of spawn blocking * waits on notify instead of display task for initial loading * includes time taken in warning and error * adds slash command to show mcp server load messages * includes mcps that fail to start in /mcp * surfaces command error for mcp servers in non-interactive mode * only surfaces timeout warning in non-interactive mode with one or more server in the client list * adds copy change for /mcp * uses a hash set of server names to keep track of the number of initialized servers * only shows mcp non-interactive msg in non-interactive mode
1 parent 12d49f2 commit 9dd4f27

File tree

6 files changed

+435
-298
lines changed

6 files changed

+435
-298
lines changed

crates/chat-cli/src/cli/chat/command.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub enum Command {
5858
path: String,
5959
force: bool,
6060
},
61+
Mcp,
6162
}
6263

6364
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -837,6 +838,7 @@ impl Command {
837838
}
838839
Self::Save { path, force }
839840
},
841+
"mcp" => Self::Mcp,
840842
unknown_command => {
841843
let looks_like_path = {
842844
let after_slash_command_str = parts[1..].join(" ");

crates/chat-cli/src/cli/chat/mod.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ use token_counter::{
107107
use tokio::signal::ctrl_c;
108108
use tool_manager::{
109109
GetPromptError,
110+
LoadingRecord,
110111
McpServerConfig,
111112
PromptBundle,
112113
ToolManager,
@@ -204,7 +205,7 @@ const WELCOME_TEXT: &str = color_print::cstr! {"<cyan!>
204205
const SMALL_SCREEN_WELCOME_TEXT: &str = color_print::cstr! {"<em>Welcome to <cyan!>Amazon Q</cyan!>!</em>"};
205206
const RESUME_TEXT: &str = color_print::cstr! {"<em>Picking up where we left off...</em>"};
206207

207-
const ROTATING_TIPS: [&str; 12] = [
208+
const ROTATING_TIPS: [&str; 13] = [
208209
color_print::cstr! {"You can resume the last conversation from your current directory by launching with <green!>q chat --resume</green!>"},
209210
color_print::cstr! {"Get notified whenever Q CLI finishes responding. Just run <green!>q settings chat.enableNotifications true</green!>"},
210211
color_print::cstr! {"You can use <green!>/editor</green!> to edit your prompt with a vim-like experience"},
@@ -217,6 +218,7 @@ const ROTATING_TIPS: [&str; 12] = [
217218
color_print::cstr! {"If you want to file an issue to the Q CLI team, just tell me, or run <green!>q issue</green!>"},
218219
color_print::cstr! {"You can enable custom tools with <green!>MCP servers</green!>. Learn more with /help"},
219220
color_print::cstr! {"You can specify wait time (in ms) for mcp server loading with <green!>q settings mcp.initTimeout {timeout in int}</green!>. Servers that takes longer than the specified time will continue to load in the background. Use /tools to see pending servers."},
221+
color_print::cstr! {"You can see the server load status as well as any warnings or errors associated with <green!>/mcp</green!>"},
220222
];
221223

222224
const GREETING_BREAK_POINT: usize = 80;
@@ -246,6 +248,7 @@ const HELP_TEXT: &str = color_print::cstr! {"
246248
<em>untrust</em> <black!>Revert a tool or tools to per-request confirmation</black!>
247249
<em>trustall</em> <black!>Trust all tools (equivalent to deprecated /acceptall)</black!>
248250
<em>reset</em> <black!>Reset all tools to default permission levels</black!>
251+
<em>/mcp</em> <black!>See mcp server loaded</black!>
249252
<em>/profile</em> <black!>Manage profiles</black!>
250253
<em>help</em> <black!>Show profile help</black!>
251254
<em>list</em> <black!>List profiles</black!>
@@ -2949,6 +2952,53 @@ impl ChatContext {
29492952
skip_printing_tools: true,
29502953
}
29512954
},
2955+
Command::Mcp => {
2956+
let terminal_width = self.terminal_width();
2957+
let loaded_servers = self.conversation_state.tool_manager.mcp_load_record.lock().await;
2958+
let still_loading = self
2959+
.conversation_state
2960+
.tool_manager
2961+
.pending_clients()
2962+
.await
2963+
.into_iter()
2964+
.map(|name| format!(" - {name}\n"))
2965+
.collect::<Vec<_>>()
2966+
.join("");
2967+
for (server_name, msg) in loaded_servers.iter() {
2968+
let msg = msg
2969+
.iter()
2970+
.map(|record| match record {
2971+
LoadingRecord::Err(content)
2972+
| LoadingRecord::Warn(content)
2973+
| LoadingRecord::Success(content) => content.clone(),
2974+
})
2975+
.collect::<Vec<_>>()
2976+
.join("\n--- tools refreshed ---\n");
2977+
queue!(
2978+
self.output,
2979+
style::Print(server_name),
2980+
style::Print("\n"),
2981+
style::Print(format!("{}\n", "▔".repeat(terminal_width))),
2982+
style::Print(msg),
2983+
style::Print("\n")
2984+
)?;
2985+
}
2986+
if !still_loading.is_empty() {
2987+
queue!(
2988+
self.output,
2989+
style::Print("Still loading:\n"),
2990+
style::Print(format!("{}\n", "▔".repeat(terminal_width))),
2991+
style::Print(still_loading),
2992+
style::Print("\n")
2993+
)?;
2994+
}
2995+
self.output.flush()?;
2996+
ChatState::PromptUser {
2997+
tool_uses: None,
2998+
pending_tool_index: None,
2999+
skip_printing_tools: true,
3000+
}
3001+
},
29523002
})
29533003
}
29543004

crates/chat-cli/src/cli/chat/server_messenger.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,23 @@ use crate::mcp_client::{
1414
};
1515

1616
#[allow(dead_code)]
17-
#[derive(Clone, Debug)]
17+
#[derive(Debug)]
1818
pub enum UpdateEventMessage {
1919
ToolsListResult {
2020
server_name: String,
21-
result: ToolsListResult,
21+
result: eyre::Result<ToolsListResult>,
2222
},
2323
PromptsListResult {
2424
server_name: String,
25-
result: PromptsListResult,
25+
result: eyre::Result<PromptsListResult>,
2626
},
2727
ResourcesListResult {
2828
server_name: String,
29-
result: ResourcesListResult,
29+
result: eyre::Result<ResourcesListResult>,
3030
},
3131
ResourceTemplatesListResult {
3232
server_name: String,
33-
result: ResourceTemplatesListResult,
33+
result: eyre::Result<ResourceTemplatesListResult>,
3434
},
3535
InitStart {
3636
server_name: String,
@@ -67,7 +67,7 @@ pub struct ServerMessenger {
6767

6868
#[async_trait::async_trait]
6969
impl Messenger for ServerMessenger {
70-
async fn send_tools_list_result(&self, result: ToolsListResult) -> Result<(), MessengerError> {
70+
async fn send_tools_list_result(&self, result: eyre::Result<ToolsListResult>) -> Result<(), MessengerError> {
7171
Ok(self
7272
.update_event_sender
7373
.send(UpdateEventMessage::ToolsListResult {
@@ -78,7 +78,7 @@ impl Messenger for ServerMessenger {
7878
.map_err(|e| MessengerError::Custom(e.to_string()))?)
7979
}
8080

81-
async fn send_prompts_list_result(&self, result: PromptsListResult) -> Result<(), MessengerError> {
81+
async fn send_prompts_list_result(&self, result: eyre::Result<PromptsListResult>) -> Result<(), MessengerError> {
8282
Ok(self
8383
.update_event_sender
8484
.send(UpdateEventMessage::PromptsListResult {
@@ -89,7 +89,10 @@ impl Messenger for ServerMessenger {
8989
.map_err(|e| MessengerError::Custom(e.to_string()))?)
9090
}
9191

92-
async fn send_resources_list_result(&self, result: ResourcesListResult) -> Result<(), MessengerError> {
92+
async fn send_resources_list_result(
93+
&self,
94+
result: eyre::Result<ResourcesListResult>,
95+
) -> Result<(), MessengerError> {
9396
Ok(self
9497
.update_event_sender
9598
.send(UpdateEventMessage::ResourcesListResult {
@@ -102,7 +105,7 @@ impl Messenger for ServerMessenger {
102105

103106
async fn send_resource_templates_list_result(
104107
&self,
105-
result: ResourceTemplatesListResult,
108+
result: eyre::Result<ResourceTemplatesListResult>,
106109
) -> Result<(), MessengerError> {
107110
Ok(self
108111
.update_event_sender

0 commit comments

Comments
 (0)