use inquire::Select;
use owo_colors::OwoColorize;
use crate::error::Result;
use crate::output::{print_success, print_warning};
use super::{read_config, server_entry, write_config, McpClient, MCP_URL, SERVER_NAME};
pub fn run(client_slug: Option<&str>) -> Result<()> {
println!("\n{}\n", " partiri mcp install".bold().cyan());
let client = match client_slug {
Some(slug) => McpClient::from_slug(slug).ok_or_else(|| {
format!(
"Unknown client '{}'. Valid options: {}",
slug,
McpClient::ALL
.iter()
.map(|c| c.slug())
.collect::<Vec<_>>()
.join(", ")
)
})?,
None => {
let options: Vec<&McpClient> = McpClient::ALL.iter().collect();
let selection = Select::new(
"Which tool do you want to install the MCP server into?",
options,
)
.prompt()
.map_err(|_| "Cancelled.")?;
*selection
}
};
let config_path = client
.config_path()
.ok_or("Could not determine config directory for this platform.")?;
let mut config = read_config(&config_path)?;
let key = client.servers_key();
let servers = config
.as_object_mut()
.ok_or("Config file is not a JSON object.")?
.entry(key)
.or_insert_with(|| serde_json::json!({}));
if servers.get(SERVER_NAME).is_some() {
print_warning(&format!(
"A '{}' entry already exists in {}. It will be overwritten.",
SERVER_NAME,
config_path.display()
));
}
servers
.as_object_mut()
.ok_or(format!("'{}' in config is not a JSON object.", key))?
.insert(SERVER_NAME.to_string(), server_entry());
write_config(&config_path, &config)?;
print_success(&format!(
"Installed MCP server into {} ({})",
client.display_name(),
config_path.display()
));
if client == McpClient::ClaudeDesktop {
println!(
" {} Restart Claude Desktop for changes to take effect.",
"→".dimmed()
);
}
println!(
"\n {} To also set up ChatGPT Desktop, add the server manually:",
"tip:".dimmed()
);
println!(
" {} Settings → Tools → Add MCP Server → Use URL: {}",
"".dimmed(),
MCP_URL.bold()
);
Ok(())
}