From 814ae3f7b375b6c9d33a9534d99070c5ac162d66 Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 14 May 2025 13:40:57 -0700 Subject: [PATCH 1/5] diasble warining in non-interactive way --- crates/chat-cli/src/cli/chat/mcp.rs | 26 ++++++++++++++++-------- crates/chat-cli/src/cli/chat/mod.rs | 15 ++++++++------ crates/chat-cli/src/database/settings.rs | 3 +++ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/crates/chat-cli/src/cli/chat/mcp.rs b/crates/chat-cli/src/cli/chat/mcp.rs index 1b9cf6aac8..29bf0ce579 100644 --- a/crates/chat-cli/src/cli/chat/mcp.rs +++ b/crates/chat-cli/src/cli/chat/mcp.rs @@ -60,7 +60,7 @@ pub async fn add_mcp_server(ctx: &Context, output: &mut SharedWriter, args: McpA if config.mcp_servers.contains_key(&args.name) && !args.force { bail!( - "MCP server '{}' already exists in {} (scope {}). Use --force to overwrite.", + "\nMCP server '{}' already exists in {} (scope {}). Use --force to overwrite.", args.name, config_path.display(), scope @@ -74,11 +74,16 @@ pub async fn add_mcp_server(ctx: &Context, output: &mut SharedWriter, args: McpA "timeout": args.timeout.unwrap_or(default_timeout()), }))?; + writeln!( + output, + "\nTo learn more about MCP safety, see https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-mcp-security.html\n\n" + )?; + config.mcp_servers.insert(args.name.clone(), tool); config.save_to_file(ctx, &config_path).await?; writeln!( output, - "✓ Added MCP server '{}' to {}", + "✓ Added MCP server '{}' to {}\n", args.name, scope_display(&scope, &args.profile) )?; @@ -100,7 +105,7 @@ pub async fn remove_mcp_server(ctx: &Context, output: &mut SharedWriter, args: M config.save_to_file(ctx, &config_path).await?; writeln!( output, - "✓ Removed MCP server '{}' from {}", + "\n✓ Removed MCP server '{}' from {}\n", args.name, scope_display(&scope, &args.profile) )?; @@ -108,7 +113,7 @@ pub async fn remove_mcp_server(ctx: &Context, output: &mut SharedWriter, args: M None => { writeln!( output, - "No MCP server named '{}' found in {}", + "\nNo MCP server named '{}' found in {}\n", args.name, scope_display(&scope, &args.profile) )?; @@ -154,7 +159,7 @@ pub async fn import_mcp_server(ctx: &Context, output: &mut SharedWriter, args: M for (name, cfg) in src_cfg.mcp_servers { if dst_cfg.mcp_servers.contains_key(&name) && !args.force { bail!( - "MCP server '{}' already exists in {} (scope {}). Use --force to overwrite.", + "MCP server '{}' already exists in {} (scope {}). Use --force to overwrite.\n", name, config_path.display(), scope @@ -164,10 +169,15 @@ pub async fn import_mcp_server(ctx: &Context, output: &mut SharedWriter, args: M added += 1; } + writeln!( + output, + "\nTo learn more about MCP safety, see https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-mcp-security.html\n\n" + )?; + dst_cfg.save_to_file(ctx, &config_path).await?; writeln!( output, - "✓ Imported {added} MCP server(s) into {}", + "✓ Imported {added} MCP server(s) into {}\n", scope_display(&scope, &args.profile) )?; Ok(()) @@ -199,7 +209,7 @@ pub async fn get_mcp_server_status(ctx: &Context, output: &mut SharedWriter, nam writeln!(output, "\n")?; if !found { - bail!("No MCP server named '{name}' found in any scope/profile"); + bail!("No MCP server named '{name}' found in any scope/profile\n"); } Ok(()) } @@ -297,7 +307,7 @@ async fn ensure_config_file( ctx.fs().create_dir_all(parent).await?; } McpServerConfig::default().save_to_file(ctx, path).await?; - writeln!(out, "📁 Created MCP config in '{}'", path.display())?; + writeln!(out, "\n📁 Created MCP config in '{}'", path.display())?; } load_cfg(ctx, path).await } diff --git a/crates/chat-cli/src/cli/chat/mod.rs b/crates/chat-cli/src/cli/chat/mod.rs index 7af54a397b..cf961cb824 100644 --- a/crates/chat-cli/src/cli/chat/mod.rs +++ b/crates/chat-cli/src/cli/chat/mod.rs @@ -354,12 +354,15 @@ pub async fn chat( let mcp_server_configs = match McpServerConfig::load_config(&mut output).await { Ok(config) => { - execute!( - output, - style::Print( - "To learn more about MCP safety, see https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-mcp-security.html\n\n" - ) - )?; + if interactive && !database.settings.get_bool(Setting::McpLoadedBefore).unwrap_or(false) { + execute!( + output, + style::Print( + "To learn more about MCP safety, see https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-mcp-security.html\n\n" + ) + )?; + } + database.settings.set(Setting::McpLoadedBefore, true).await?; config }, Err(e) => { diff --git a/crates/chat-cli/src/database/settings.rs b/crates/chat-cli/src/database/settings.rs index b2beaf0887..c35d609c92 100644 --- a/crates/chat-cli/src/database/settings.rs +++ b/crates/chat-cli/src/database/settings.rs @@ -29,6 +29,7 @@ pub enum Setting { ApiCodeWhispererService, ApiQService, McpInitTimeout, + McpLoadedBefore, } impl AsRef for Setting { @@ -46,6 +47,7 @@ impl AsRef for Setting { Self::ApiCodeWhispererService => "api.codewhisperer.service", Self::ApiQService => "api.q.service", Self::McpInitTimeout => "mcp.initTimeout", + Self::McpLoadedBefore => "mcp.loadedBefore", } } } @@ -73,6 +75,7 @@ impl TryFrom<&str> for Setting { "api.codewhisperer.service" => Ok(Self::ApiCodeWhispererService), "api.q.service" => Ok(Self::ApiQService), "mcp.initTimeout" => Ok(Self::McpInitTimeout), + "mcp.loadedBefore" => Ok(Self::McpLoadedBefore), _ => Err(DatabaseError::InvalidSetting(value.to_string())), } } From c88ba69a7a8c404dd37e7524bc1a6ba39e062e2c Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 14 May 2025 13:56:22 -0700 Subject: [PATCH 2/5] add test --- crates/chat-cli/src/cli/chat/mcp.rs | 2 +- crates/chat-cli/src/database/settings.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/chat-cli/src/cli/chat/mcp.rs b/crates/chat-cli/src/cli/chat/mcp.rs index 5b52a0126e..827cbceab7 100644 --- a/crates/chat-cli/src/cli/chat/mcp.rs +++ b/crates/chat-cli/src/cli/chat/mcp.rs @@ -159,7 +159,7 @@ pub async fn import_mcp_server(ctx: &Context, output: &mut SharedWriter, args: M for (name, cfg) in src_cfg.mcp_servers { if dst_cfg.mcp_servers.contains_key(&name) && !args.force { bail!( - "MCP server '{}' already exists in {} (scope {}). Use --force to overwrite.\n", + "\nMCP server '{}' already exists in {} (scope {}). Use --force to overwrite.\n", name, config_path.display(), scope diff --git a/crates/chat-cli/src/database/settings.rs b/crates/chat-cli/src/database/settings.rs index c35d609c92..998ade3ba0 100644 --- a/crates/chat-cli/src/database/settings.rs +++ b/crates/chat-cli/src/database/settings.rs @@ -193,10 +193,12 @@ mod test { assert_eq!(settings.get(Setting::TelemetryEnabled), None); assert_eq!(settings.get(Setting::OldClientId), None); assert_eq!(settings.get(Setting::ShareCodeWhispererContent), None); + assert_eq!(settings.get(Setting::McpLoadedBefore), None); settings.set(Setting::TelemetryEnabled, true).await.unwrap(); settings.set(Setting::OldClientId, "test").await.unwrap(); settings.set(Setting::ShareCodeWhispererContent, false).await.unwrap(); + settings.set(Setting::McpLoadedBefore, true).await.unwrap(); assert_eq!(settings.get(Setting::TelemetryEnabled), Some(&Value::Bool(true))); assert_eq!( @@ -207,13 +209,16 @@ mod test { settings.get(Setting::ShareCodeWhispererContent), Some(&Value::Bool(false)) ); + assert_eq!(settings.get(Setting::McpLoadedBefore),Some(&Value::Bool(true))); settings.remove(Setting::TelemetryEnabled).await.unwrap(); settings.remove(Setting::OldClientId).await.unwrap(); settings.remove(Setting::ShareCodeWhispererContent).await.unwrap(); + settings.remove(Setting::McpLoadedBefore).await.unwrap(); assert_eq!(settings.get(Setting::TelemetryEnabled), None); assert_eq!(settings.get(Setting::OldClientId), None); assert_eq!(settings.get(Setting::ShareCodeWhispererContent), None); + assert_eq!(settings.get(Setting::McpLoadedBefore), None); } } From 1b3d2a0c06a7e87a023696f9bd20b185b508992b Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Wed, 14 May 2025 13:57:58 -0700 Subject: [PATCH 3/5] fmt --- crates/chat-cli/src/database/settings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/chat-cli/src/database/settings.rs b/crates/chat-cli/src/database/settings.rs index 998ade3ba0..1830bc74e1 100644 --- a/crates/chat-cli/src/database/settings.rs +++ b/crates/chat-cli/src/database/settings.rs @@ -209,7 +209,7 @@ mod test { settings.get(Setting::ShareCodeWhispererContent), Some(&Value::Bool(false)) ); - assert_eq!(settings.get(Setting::McpLoadedBefore),Some(&Value::Bool(true))); + assert_eq!(settings.get(Setting::McpLoadedBefore), Some(&Value::Bool(true))); settings.remove(Setting::TelemetryEnabled).await.unwrap(); settings.remove(Setting::OldClientId).await.unwrap(); From e0ae0cb7f73ba3ee377a2cd9eceb8e29b2020e2f Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 19 May 2025 16:46:17 -0700 Subject: [PATCH 4/5] add vim tip --- crates/chat-cli/src/cli/chat/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/chat-cli/src/cli/chat/mod.rs b/crates/chat-cli/src/cli/chat/mod.rs index 4e01ea8192..68b112eb3c 100644 --- a/crates/chat-cli/src/cli/chat/mod.rs +++ b/crates/chat-cli/src/cli/chat/mod.rs @@ -276,6 +276,7 @@ const HELP_TEXT: &str = color_print::cstr! {" Ctrl(^) + j Insert new-line to provide multi-line prompt. Alternatively, [Alt(⌥) + Enter(⏎)] Ctrl(^) + s Fuzzy search commands and context files. Use Tab to select multiple items. Change the keybind to ctrl+x with: q settings chat.skimCommandKey x (where x is any key) +chat.editMode Set editing mode (vim or emacs) using: q settings chat.editMode vi/emacs "}; From 1e8ae10c9639bd9bbaa53218ba0b6916cd51aabf Mon Sep 17 00:00:00 2001 From: YIFAN LIU Date: Mon, 19 May 2025 16:53:02 -0700 Subject: [PATCH 5/5] trigger ci