Skip to content

Commit 91dbeec

Browse files
committed
add mcp list command
1 parent 8ac4dcc commit 91dbeec

File tree

4 files changed

+68
-9
lines changed

4 files changed

+68
-9
lines changed

crates/q_chat/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod context;
55
mod conversation_state;
66
mod hooks;
77
mod input_source;
8-
mod mcp;
8+
pub mod mcp;
99
mod message;
1010
mod parse;
1111
mod parser;

crates/q_chat/src/mcp.rs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,77 @@ pub async fn remove_mcp_server(ctx: &Context, args: McpRemove) -> Result<()> {
6868
}
6969

7070
pub async fn list_mcp_server(ctx: &Context, args: McpList) -> Result<()> {
71-
todo!()
71+
let configs = get_mcp_server_configs(ctx, args.scope, args.profile).await?;
72+
if configs.is_empty() {
73+
println!("No MCP server configurations found.\n");
74+
return Ok(());
75+
}
76+
77+
for (scope, profile, path, cfg_opt) in configs {
78+
println!("{}:", scope_display(&scope, &profile));
79+
println!(" {}", path.display());
80+
match cfg_opt {
81+
Some(cfg) if !cfg.mcp_servers.is_empty() => {
82+
for (name, tool_cfg) in &cfg.mcp_servers {
83+
println!(" • {name:<12} {}", tool_cfg.command);
84+
}
85+
},
86+
_ => {
87+
println!(" null");
88+
},
89+
}
90+
}
91+
Ok(())
7292
}
7393

7494
async fn get_mcp_server_configs(
7595
ctx: &Context,
7696
scope: Option<Scope>,
7797
profile: Option<String>,
78-
) -> Result<Vec<(PathBuf, McpServerConfig)>> {
79-
todo!()
98+
) -> Result<Vec<(Scope, Option<String>, PathBuf, Option<McpServerConfig>)>> {
99+
let targets: Vec<(Scope, Option<String>)> = match (scope, profile) {
100+
(Some(Scope::Workspace), _) => vec![(Scope::Workspace, None)],
101+
(Some(Scope::Global), _) => vec![(Scope::Global, None)],
102+
(Some(Scope::Profile), Some(p)) => vec![(Scope::Profile, Some(p))],
103+
(Some(Scope::Profile), None) => vec![(Scope::Profile, Some("default".to_string()))],
104+
105+
// no scope but have profile ⇒ search profile
106+
(None, Some(p)) => vec![(Scope::Profile, Some(p))],
107+
108+
// give nothing ⇒ default priority:workspace → global
109+
(None, None) => vec![
110+
(Scope::Workspace, None),
111+
(Scope::Global, None),
112+
(Scope::Profile, Some("default".to_string())),
113+
],
114+
};
115+
116+
let mut results = Vec::new();
117+
for (sc, prof) in targets {
118+
let path = resolve_scope_profile(ctx, Some(sc), prof.as_ref())?;
119+
120+
let cfg_opt = if ctx.fs().exists(&path) {
121+
match McpServerConfig::load_from_file(ctx, &path).await {
122+
Ok(cfg) => Some(cfg),
123+
Err(e) => {
124+
warn!(?path, error = %e, "Invalid MCP config file—ignored, treated as null");
125+
None
126+
},
127+
}
128+
} else {
129+
None
130+
};
131+
results.push((sc, prof.clone(), path, cfg_opt));
132+
}
133+
Ok(results)
134+
}
135+
136+
fn scope_display(scope: &Scope, profile: &Option<String>) -> String {
137+
match scope {
138+
Scope::Workspace => "\n📄 workspace".into(),
139+
Scope::Global => "\n🌍 global".into(),
140+
Scope::Profile => format!("\n👤 profile({})", profile.as_deref().unwrap_or("default")),
141+
}
80142
}
81143

82144
pub async fn import_mcp_server(ctx: &Context, args: McpImport) -> Result<()> {

crates/q_chat/src/tool_manager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub fn profile_mcp_config_path<Ctx: FsProvider + EnvProvider>(
8484
ctx: &Ctx,
8585
profile_name: impl AsRef<str>,
8686
) -> eyre::Result<PathBuf> {
87-
Ok(chat_profiles_dir(ctx)?.join(profile_name.as_ref()).join("mcp.join"))
87+
Ok(chat_profiles_dir(ctx)?.join(profile_name.as_ref()).join("mcp.json"))
8888
}
8989

9090
pub fn global_mcp_config_path<Ctx: FsProvider + EnvProvider>(ctx: &Ctx) -> eyre::Result<PathBuf> {

crates/q_cli/src/cli/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,7 @@ impl Cli {
341341
CliRootCommands::Version { changelog } => Self::print_version(changelog),
342342
CliRootCommands::Dashboard => launch_dashboard(false).await,
343343
CliRootCommands::Chat(args) => q_chat::launch_chat(args).await,
344-
CliRootCommands::Mcp(args) => {
345-
println!("{:?}", args);
346-
Ok(ExitCode::SUCCESS)
347-
},
344+
CliRootCommands::Mcp(args) => q_chat::mcp::execute_mcp(args).await,
348345
CliRootCommands::Inline(subcommand) => subcommand.execute(&cli_context).await,
349346
},
350347
// Root command

0 commit comments

Comments
 (0)