Skip to content

Commit 5bf85d1

Browse files
committed
merge refactor changes, keep all in chat_cli
1 parent fcac0bb commit 5bf85d1

4 files changed

Lines changed: 135 additions & 242 deletions

File tree

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,30 @@ use eyre::{
1111
Result,
1212
bail,
1313
};
14-
use fig_os_shim::Context;
15-
use fig_util::directories::chat_profiles_dir;
1614
use tokio::fs;
1715
use tracing::warn;
1816

19-
use crate::cli::{
17+
use crate::cli::chat::cli::{
2018
Mcp,
2119
McpAdd,
2220
McpImport,
2321
McpList,
2422
McpRemove,
2523
Scope,
2624
};
27-
use crate::tool_manager::{
25+
use crate::cli::chat::tool_manager::{
2826
McpServerConfig,
2927
global_mcp_config_path,
3028
profile_mcp_config_path,
3129
workspace_mcp_config_path,
3230
};
33-
use crate::tools::custom_tool::{
31+
use crate::cli::chat::tools::custom_tool::{
3432
CustomToolConfig,
3533
default_timeout,
3634
};
37-
use crate::util::shared_writer::SharedWriter;
35+
use crate::cli::chat::util::shared_writer::SharedWriter;
36+
use crate::platform::Context;
37+
use crate::util::directories::chat_profiles_dir;
3838

3939
pub async fn execute_mcp(args: Mcp) -> Result<ExitCode> {
4040
let ctx = Context::new();
@@ -367,7 +367,7 @@ mod tests {
367367

368368
#[tokio::test]
369369
async fn add_then_remove_cycle() {
370-
use crate::cli::{
370+
use crate::cli::chat::cli::{
371371
McpAdd,
372372
McpRemove,
373373
};

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

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,6 @@ use crossterm::{
2222
style,
2323
terminal,
2424
};
25-
use fig_api_client::model::{
26-
ToolResult,
27-
ToolResultContentBlock,
28-
ToolResultStatus,
29-
};
30-
use fig_os_shim::{
31-
Context,
32-
EnvProvider,
33-
FsProvider,
34-
};
35-
use fig_util::directories::{
36-
chat_profiles_dir,
37-
home_dir_ctx,
38-
};
3925
use futures::{
4026
StreamExt,
4127
stream,
@@ -76,27 +62,29 @@ use crate::mcp_client::{
7662
JsonRpcResponse,
7763
PromptGet,
7864
};
65+
use crate::platform::Context;
7966
use crate::telemetry::TelemetryThread;
67+
use crate::util::directories::{
68+
chat_profiles_dir,
69+
home_dir,
70+
};
8071

8172
const NAMESPACE_DELIMITER: &str = "___";
8273
// This applies for both mcp server and tool name since in the end the tool name as seen by the
8374
// model is just {server_name}{NAMESPACE_DELIMITER}{tool_name}
8475
const VALID_TOOL_NAME: &str = "^[a-zA-Z][a-zA-Z0-9_]*$";
8576
const SPINNER_CHARS: [char; 10] = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
8677

87-
pub fn workspace_mcp_config_path<Ctx: EnvProvider>(ctx: &Ctx) -> eyre::Result<PathBuf> {
78+
pub fn workspace_mcp_config_path(ctx: &Context) -> eyre::Result<PathBuf> {
8879
Ok(ctx.env().current_dir()?.join(".amazonq").join("mcp.json"))
8980
}
9081

91-
pub fn profile_mcp_config_path<Ctx: FsProvider + EnvProvider>(
92-
ctx: &Ctx,
93-
profile_name: impl AsRef<str>,
94-
) -> eyre::Result<PathBuf> {
82+
pub fn profile_mcp_config_path(ctx: &Context, profile_name: impl AsRef<str>) -> eyre::Result<PathBuf> {
9583
Ok(chat_profiles_dir(ctx)?.join(profile_name.as_ref()).join("mcp.json"))
9684
}
9785

98-
pub fn global_mcp_config_path<Ctx: FsProvider + EnvProvider>(ctx: &Ctx) -> eyre::Result<PathBuf> {
99-
Ok(home_dir_ctx(ctx)?.join(".aws").join("amazonq").join("mcp.json"))
86+
pub fn global_mcp_config_path(ctx: &Context) -> eyre::Result<PathBuf> {
87+
Ok(home_dir(ctx)?.join(".aws").join("amazonq").join("mcp.json"))
10088
}
10189

10290
#[derive(Debug, Error)]
@@ -191,14 +179,14 @@ impl McpServerConfig {
191179
}
192180

193181
pub async fn load_from_file(ctx: &Context, path: impl AsRef<Path>) -> eyre::Result<Self> {
194-
Ok(serde_json::from_str(&ctx.fs().read_to_string(path.as_ref()).await?)?)
182+
let contents = ctx.fs().read_to_string(path.as_ref()).await?;
183+
Ok(serde_json::from_str(&contents)?)
195184
}
196185

197186
pub async fn save_to_file(&self, ctx: &Context, path: impl AsRef<Path>) -> eyre::Result<()> {
198-
Ok(ctx
199-
.fs()
200-
.write(path.as_ref(), serde_json::to_string_pretty(self)?)
201-
.await?)
187+
let json = serde_json::to_string_pretty(self)?;
188+
ctx.fs().write(path.as_ref(), json).await?;
189+
Ok(())
202190
}
203191

204192
fn from_slice(slice: &[u8], output: &mut impl Write, location: &str) -> eyre::Result<McpServerConfig> {

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

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ use tracing::{
3434
debug,
3535
};
3636
use user::UserSubcommand;
37-
37+
use crate::cli::chat::mcp;
38+
use crate::cli::chat::cli::Mcp;
3839
use crate::logging::{
3940
LogArgs,
4041
initialize_logging,
@@ -104,6 +105,9 @@ pub enum CliRootCommands {
104105
/// AI assistant in your terminal
105106
#[command(alias("q"))]
106107
Chat(Chat),
108+
/// Model Context Protocol (MCP)
109+
#[command(subcommand)]
110+
Mcp(Mcp),
107111
}
108112

109113
impl CliRootCommands {
@@ -118,6 +122,7 @@ impl CliRootCommands {
118122
CliRootCommands::User(UserSubcommand::Profile) => "profile",
119123
CliRootCommands::Version { .. } => "version",
120124
CliRootCommands::Chat { .. } => "chat",
125+
CliRootCommands::Mcp(_) => "mcp",
121126
}
122127
}
123128
}
@@ -206,6 +211,7 @@ impl Cli {
206211
CliRootCommands::Issue(args) => args.execute().await,
207212
CliRootCommands::Version { changelog } => Self::print_version(changelog),
208213
CliRootCommands::Chat(args) => chat::launch_chat(&mut database, &telemetry, args).await,
214+
CliRootCommands::Mcp(args) => mcp::execute_mcp(args).await,
209215
},
210216
// Root command
211217
None => chat::launch_chat(&mut database, &telemetry, chat::cli::Chat::default()).await,
@@ -308,6 +314,13 @@ impl Cli {
308314

309315
#[cfg(test)]
310316
mod test {
317+
use crate::cli::chat::cli::{
318+
McpAdd,
319+
McpImport,
320+
McpList,
321+
McpRemove,
322+
Scope,
323+
};
311324
use super::*;
312325

313326
#[test]
@@ -490,4 +503,89 @@ mod test {
490503
})
491504
);
492505
}
506+
#[test]
507+
fn test_mcp_subcomman_add() {
508+
assert_parse!(
509+
[
510+
"mcp",
511+
"add",
512+
"--name",
513+
"test_server",
514+
"--command",
515+
"test_command",
516+
"--profile",
517+
"my_profile",
518+
"--env",
519+
"key1=value1,key2=value2"
520+
],
521+
CliRootCommands::Mcp(Mcp::Add(McpAdd {
522+
name: "test_server".to_string(),
523+
command: "test_command".to_string(),
524+
scope: None,
525+
profile: Some("my_profile".to_string()),
526+
env: vec![
527+
[
528+
("key1".to_string(), "value1".to_string()),
529+
("key2".to_string(), "value2".to_string())
530+
]
531+
.into_iter()
532+
.collect()
533+
],
534+
timeout: None,
535+
force: false,
536+
}))
537+
);
538+
}
539+
540+
#[test]
541+
fn test_mcp_subcomman_remove_workspace() {
542+
assert_parse!(
543+
["mcp", "remove", "--name", "old"],
544+
CliRootCommands::Mcp(Mcp::Remove(McpRemove {
545+
name: "old".into(),
546+
scope: None,
547+
profile: None,
548+
}))
549+
);
550+
}
551+
#[test]
552+
fn test_mcp_subcomman_import_profile_force() {
553+
assert_parse!(
554+
[
555+
"mcp",
556+
"import",
557+
"--file",
558+
"servers.json",
559+
"profile",
560+
"--profile",
561+
"qa",
562+
"--force"
563+
],
564+
CliRootCommands::Mcp(Mcp::Import(McpImport {
565+
file: "servers.json".into(),
566+
scope: Some(Scope::Profile),
567+
profile: Some("qa".into()),
568+
force: true,
569+
}))
570+
);
571+
}
572+
573+
#[test]
574+
fn test_mcp_subcommand_status_simple() {
575+
assert_parse!(
576+
["mcp", "status", "--name", "aws"],
577+
CliRootCommands::Mcp(Mcp::Status { name: "aws".into() })
578+
);
579+
}
580+
581+
#[test]
582+
fn test_mcp_subcommand_list() {
583+
assert_parse!(
584+
["mcp", "list", "global"],
585+
CliRootCommands::Mcp(Mcp::List(McpList {
586+
scope: Some(Scope::Global),
587+
profile: None
588+
}))
589+
);
590+
}
493591
}

0 commit comments

Comments
 (0)