@@ -215,7 +215,7 @@ pub struct McpServers {
215215 pub mcp_servers : HashMap < String , McpServerConfig > ,
216216}
217217
218- #[ derive( Debug , Clone , Serialize , Deserialize , JsonSchema ) ]
218+ #[ derive( Debug , Clone , Serialize , JsonSchema ) ]
219219#[ serde( tag = "type" ) ]
220220pub enum McpServerConfig {
221221 #[ serde( rename = "stdio" ) ]
@@ -224,6 +224,49 @@ pub enum McpServerConfig {
224224 Remote ( RemoteMcpServerConfig ) ,
225225}
226226
227+ impl < ' de > Deserialize < ' de > for McpServerConfig {
228+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
229+ where
230+ D : serde:: Deserializer < ' de > ,
231+ {
232+ use serde:: de:: Error ;
233+
234+ // Helper enum with derived Deserialize to avoid infinite recursion
235+ #[ derive( Deserialize ) ]
236+ #[ serde( tag = "type" ) ]
237+ enum McpServerConfigHelper {
238+ #[ serde( rename = "stdio" ) ]
239+ Local ( LocalMcpServerConfig ) ,
240+ #[ serde( rename = "http" ) ]
241+ Remote ( RemoteMcpServerConfig ) ,
242+ }
243+
244+ let value = serde_json:: Value :: deserialize ( deserializer) ?;
245+
246+ // Check if "type" field exists
247+ if let Some ( obj) = value. as_object ( ) {
248+ if !obj. contains_key ( "type" ) {
249+ // If "type" is missing, default to "stdio" by adding it
250+ let mut obj = obj. clone ( ) ;
251+ obj. insert ( "type" . to_string ( ) , serde_json:: Value :: String ( "stdio" . to_string ( ) ) ) ;
252+ let value_with_type = serde_json:: Value :: Object ( obj) ;
253+ let helper: McpServerConfigHelper = serde_json:: from_value ( value_with_type) . map_err ( D :: Error :: custom) ?;
254+ return Ok ( match helper {
255+ McpServerConfigHelper :: Local ( config) => McpServerConfig :: Local ( config) ,
256+ McpServerConfigHelper :: Remote ( config) => McpServerConfig :: Remote ( config) ,
257+ } ) ;
258+ }
259+ }
260+
261+ // Normal deserialization with type field present
262+ let helper: McpServerConfigHelper = serde_json:: from_value ( value) . map_err ( D :: Error :: custom) ?;
263+ Ok ( match helper {
264+ McpServerConfigHelper :: Local ( config) => McpServerConfig :: Local ( config) ,
265+ McpServerConfigHelper :: Remote ( config) => McpServerConfig :: Remote ( config) ,
266+ } )
267+ }
268+ }
269+
227270#[ derive( Debug , Clone , Serialize , Deserialize , JsonSchema ) ]
228271#[ serde( rename_all = "camelCase" ) ]
229272pub struct LocalMcpServerConfig {
@@ -471,6 +514,23 @@ mod tests {
471514 }
472515 }
473516
517+ #[ test]
518+ fn test_mcp_server_config_defaults_to_stdio ( ) {
519+ // Test that when "type" field is missing, it defaults to "stdio" (Local variant)
520+ let config = serde_json:: json!( {
521+ "command" : "node" ,
522+ "args" : [ "server.js" ]
523+ } ) ;
524+ let result: McpServerConfig = serde_json:: from_value ( config) . unwrap ( ) ;
525+ match result {
526+ McpServerConfig :: Local ( local) => {
527+ assert_eq ! ( local. command, "node" ) ;
528+ assert_eq ! ( local. args, vec![ "server.js" ] ) ;
529+ } ,
530+ _ => panic ! ( "Expected Local variant when type field is missing" ) ,
531+ }
532+ }
533+
474534 #[ test]
475535 fn test_mcp_servers_map_deser ( ) {
476536 let servers = serde_json:: json!( {
0 commit comments