|
2 | 2 |
|
3 | 3 | use anyhow::{Context, Result, bail}; |
4 | 4 | use clap::{ArgGroup, Parser}; |
5 | | -use cortex_common::dirs::get_cortex_home; |
6 | 5 | use cortex_common::CliConfigOverrides; |
| 6 | +use cortex_common::dirs::get_cortex_home; |
7 | 7 | use std::io::{self, BufRead, Write}; |
8 | 8 |
|
9 | 9 | // ============================================================================ |
@@ -308,6 +308,10 @@ pub struct AddArgs { |
308 | 308 | /// Name for the MCP server configuration. |
309 | 309 | pub name: String, |
310 | 310 |
|
| 311 | + /// Force overwrite if server already exists. |
| 312 | + #[arg(short, long)] |
| 313 | + pub force: bool, |
| 314 | + |
311 | 315 | #[command(flatten)] |
312 | 316 | pub transport_args: AddMcpTransportArgs, |
313 | 317 | } |
@@ -492,6 +496,34 @@ fn get_mcp_server(name: &str) -> Result<Option<toml::Value>> { |
492 | 496 | Ok(servers.get(name).cloned()) |
493 | 497 | } |
494 | 498 |
|
| 499 | +/// Remove a specific MCP server from config (used by --force). |
| 500 | +fn remove_mcp_server_from_config(name: &str) -> Result<()> { |
| 501 | + let cortex_home = get_cortex_home_result()?; |
| 502 | + let config_path = cortex_home.join("config.toml"); |
| 503 | + |
| 504 | + if !config_path.exists() { |
| 505 | + return Ok(()); |
| 506 | + } |
| 507 | + |
| 508 | + let content = std::fs::read_to_string(&config_path) |
| 509 | + .with_context(|| format!("failed to read config: {}", config_path.display()))?; |
| 510 | + |
| 511 | + let mut config: toml::Value = |
| 512 | + toml::from_str(&content).with_context(|| "failed to parse config")?; |
| 513 | + |
| 514 | + if let Some(mcp_servers) = config.get_mut("mcp_servers").and_then(|v| v.as_table_mut()) { |
| 515 | + mcp_servers.remove(name); |
| 516 | + } |
| 517 | + |
| 518 | + let new_content = |
| 519 | + toml::to_string_pretty(&config).with_context(|| "failed to serialize config")?; |
| 520 | + |
| 521 | + std::fs::write(&config_path, new_content) |
| 522 | + .with_context(|| format!("failed to write config: {}", config_path.display()))?; |
| 523 | + |
| 524 | + Ok(()) |
| 525 | +} |
| 526 | + |
495 | 527 | async fn run_list(args: ListArgs) -> Result<()> { |
496 | 528 | let servers = get_mcp_servers()?; |
497 | 529 |
|
@@ -662,18 +694,25 @@ async fn run_get(args: GetArgs) -> Result<()> { |
662 | 694 | async fn run_add(args: AddArgs) -> Result<()> { |
663 | 695 | let AddArgs { |
664 | 696 | name, |
| 697 | + force, |
665 | 698 | transport_args, |
666 | 699 | } = args; |
667 | 700 |
|
668 | 701 | validate_server_name(&name)?; |
669 | 702 |
|
670 | 703 | // Check if server already exists |
671 | 704 | if get_mcp_server(&name)?.is_some() { |
672 | | - bail!( |
673 | | - "MCP server '{}' already exists. Use 'Cortex mcp remove {}' first.", |
674 | | - name, |
675 | | - name |
676 | | - ); |
| 705 | + if force { |
| 706 | + // Remove existing server before adding the new one |
| 707 | + remove_mcp_server_from_config(&name)?; |
| 708 | + println!("Replacing existing MCP server '{name}'..."); |
| 709 | + } else { |
| 710 | + bail!( |
| 711 | + "MCP server '{}' already exists. Use --force to overwrite or 'Cortex mcp remove {}' first.", |
| 712 | + name, |
| 713 | + name |
| 714 | + ); |
| 715 | + } |
677 | 716 | } |
678 | 717 |
|
679 | 718 | let cortex_home = get_cortex_home_result()?; |
|
0 commit comments