@@ -23,7 +23,10 @@ use crate::tool_manager::{
2323 profile_mcp_config_path,
2424 workspace_mcp_config_path,
2525} ;
26- use crate :: tools:: custom_tool:: CustomToolConfig ;
26+ use crate :: tools:: custom_tool:: {
27+ CustomToolConfig ,
28+ default_timeout,
29+ } ;
2730
2831pub async fn execute_mcp ( args : Mcp ) -> Result < ExitCode > {
2932 let ctx = Context :: new ( ) ;
@@ -44,14 +47,33 @@ pub async fn execute_mcp(args: Mcp) -> Result<ExitCode> {
4447pub async fn add_mcp_server ( ctx : & Context , args : McpAdd ) -> Result < ( ) > {
4548 let scope = args. scope . unwrap_or ( Scope :: Workspace ) ;
4649 let config_path = resolve_scope_profile ( ctx, args. scope , args. profile . as_ref ( ) ) ?;
50+
51+ if !ctx. fs ( ) . exists ( & config_path) && scope != Scope :: Profile {
52+ if let Some ( parent) = config_path. parent ( ) {
53+ ctx. fs ( ) . create_dir_all ( parent) . await ?;
54+ }
55+ McpServerConfig :: default ( ) . save_to_file ( ctx, & config_path) . await ?;
56+ println ! ( "📁 Created MCP config in'{}'" , config_path. display( ) ) ;
57+ }
58+
4759 let mut config: McpServerConfig = serde_json:: from_str ( & ctx. fs ( ) . read_to_string ( & config_path) . await ?) ?;
48- let merged_env = args. env . into_iter ( ) . flatten ( ) . collect :: < HashMap < _ , _ > > ( ) ;
4960
61+ if config. mcp_servers . contains_key ( & args. name ) && !args. force {
62+ bail ! (
63+ "MCP server '{}' already exists in {} (scope {}). Use --force to overwrite." ,
64+ args. name,
65+ config_path. display( ) ,
66+ scope
67+ ) ;
68+ }
69+
70+ let merged_env = args. env . into_iter ( ) . flatten ( ) . collect :: < HashMap < _ , _ > > ( ) ;
5071 let tool: CustomToolConfig = serde_json:: from_value ( serde_json:: json!( {
5172 "command" : args. command,
5273 "env" : merged_env,
53- "timeout" : args. timeout,
74+ "timeout" : args. timeout. unwrap_or ( default_timeout ( ) ) ,
5475 } ) ) ?;
76+
5577 config. mcp_servers . insert ( args. name . clone ( ) , tool) ;
5678 config. save_to_file ( ctx, & config_path) . await ?;
5779
@@ -68,7 +90,7 @@ pub async fn remove_mcp_server(ctx: &Context, args: McpRemove) -> Result<()> {
6890 let config_path = resolve_scope_profile ( ctx, args. scope , args. profile . as_ref ( ) ) ?;
6991
7092 if !ctx. fs ( ) . exists ( & config_path) {
71- println ! ( "No MCP configuration at {}" , config_path . display ( ) ) ;
93+ println ! ( "\n No MCP server configurations found. \n " ) ;
7294 return Ok ( ( ) ) ;
7395 }
7496
@@ -82,7 +104,11 @@ pub async fn remove_mcp_server(ctx: &Context, args: McpRemove) -> Result<()> {
82104 scope_display( & scope, & args. profile)
83105 ) ;
84106 } ,
85- None => println ! ( "No MCP server named '{}' found in {}" , args. name, scope_display( & scope, & args. profile) ) ,
107+ None => println ! (
108+ "No MCP server named '{}' found in {}" ,
109+ args. name,
110+ scope_display( & scope, & args. profile)
111+ ) ,
86112 }
87113 Ok ( ( ) )
88114}
@@ -115,20 +141,33 @@ pub async fn list_mcp_server(ctx: &Context, args: McpList) -> Result<()> {
115141pub async fn import_mcp_server ( ctx : & Context , args : McpImport ) -> Result < ( ) > {
116142 let scope: Scope = args. scope . unwrap_or ( Scope :: Workspace ) ;
117143 let config_path = resolve_scope_profile ( ctx, args. scope , args. profile . as_ref ( ) ) ?;
118- let mut dst_cfg: McpServerConfig = if ctx. fs ( ) . exists ( & config_path) {
119- McpServerConfig :: load_from_file ( ctx, & config_path) . await ?
120- } else {
121- McpServerConfig :: default ( )
122- } ;
144+
145+ if !ctx. fs ( ) . exists ( & config_path) && scope != Scope :: Profile {
146+ if let Some ( parent) = config_path. parent ( ) {
147+ ctx. fs ( ) . create_dir_all ( parent) . await ?;
148+ }
149+ McpServerConfig :: default ( ) . save_to_file ( ctx, & config_path) . await ?;
150+ println ! ( "📁 Created MCP config in'{}'" , config_path. display( ) ) ;
151+ }
152+
123153 let src_path = expand_path ( ctx, & args. file ) ?;
124154 let src_cfg: McpServerConfig = serde_json:: from_str ( & ctx. fs ( ) . read_to_string ( & src_path) . await ?) ?;
155+ let mut dst_cfg: McpServerConfig = McpServerConfig :: load_from_file ( ctx, & config_path) . await ?;
125156
126157 let before = dst_cfg. mcp_servers . len ( ) ;
127158 for ( name, cfg) in src_cfg. mcp_servers {
128- if dst_cfg. mcp_servers . insert ( name. clone ( ) , cfg) . is_some ( ) {
129- warn ! ( %name, "Overwriting existing MCP server configuration" ) ;
159+ let exists = dst_cfg. mcp_servers . contains_key ( & name) ;
160+ if exists && !args. force {
161+ bail ! (
162+ "MCP server '{}' already exists in {} (scope {}). Use --force to overwrite." ,
163+ name,
164+ config_path. display( ) ,
165+ scope
166+ ) ;
130167 }
168+ dst_cfg. mcp_servers . insert ( name. clone ( ) , cfg) ;
131169 }
170+
132171 let added = dst_cfg. mcp_servers . len ( ) - before;
133172 dst_cfg. save_to_file ( ctx, & config_path) . await ?;
134173
0 commit comments