@@ -254,6 +254,7 @@ impl UserServerEntry {
254254 required : true ,
255255 secret : true ,
256256 description : None ,
257+ default : None ,
257258 placeholder : None ,
258259 obtain_url : None ,
259260 obtain_instructions : None ,
@@ -444,6 +445,7 @@ mod tests {
444445 required: false ,
445446 secret: false ,
446447 description: Some ( "Custom description" . to_string( ) ) ,
448+ default : None ,
447449 placeholder: None ,
448450 obtain_url: None ,
449451 obtain_instructions: None ,
@@ -649,4 +651,133 @@ mod tests {
649651 // Explicit OAuth should not be overridden
650652 assert ! ( matches!( def. auth, Some ( AuthConfig :: Oauth ) ) ) ;
651653 }
654+
655+ #[ test]
656+ fn test_input_default_value_parsed_from_json ( ) {
657+ let json = r#"{
658+ "mcpServers": {
659+ "test-server": {
660+ "command": "node",
661+ "args": ["server.js"],
662+ "env": {
663+ "LOG_LEVEL": "${input:LOG_LEVEL}"
664+ },
665+ "metadata": {
666+ "inputs": [
667+ {
668+ "id": "LOG_LEVEL",
669+ "label": "Log Level",
670+ "type": "text",
671+ "required": false,
672+ "secret": false,
673+ "default": "info"
674+ }
675+ ]
676+ }
677+ }
678+ }
679+ }"# ;
680+
681+ let config: UserSpaceConfig = serde_json:: from_str ( json) . unwrap ( ) ;
682+ let definitions =
683+ config. to_server_definitions ( "test-space" , PathBuf :: from ( "/test/path.json" ) ) ;
684+
685+ assert_eq ! ( definitions. len( ) , 1 ) ;
686+ let inputs = & definitions[ 0 ] . transport . metadata ( ) . inputs ;
687+ assert_eq ! ( inputs. len( ) , 1 ) ;
688+ assert_eq ! ( inputs[ 0 ] . id, "LOG_LEVEL" ) ;
689+ assert_eq ! ( inputs[ 0 ] . default , Some ( "info" . to_string( ) ) ) ;
690+ }
691+
692+ #[ test]
693+ fn test_explicit_input_with_default_takes_precedence_over_autodiscovery ( ) {
694+ let entry = UserServerEntry {
695+ command : Some ( "node" . to_string ( ) ) ,
696+ args : None ,
697+ env : Some ( HashMap :: from ( [ (
698+ "LOG_LEVEL" . to_string ( ) ,
699+ "${input:LOG_LEVEL}" . to_string ( ) ,
700+ ) ] ) ) ,
701+ url : None ,
702+ headers : None ,
703+ name : None ,
704+ description : None ,
705+ icon : None ,
706+ alias : None ,
707+ auth : None ,
708+ metadata : Some ( UserServerMetadata {
709+ inputs : Some ( vec ! [ InputDefinition {
710+ id: "LOG_LEVEL" . to_string( ) ,
711+ label: "Log Level" . to_string( ) ,
712+ r#type: "text" . to_string( ) ,
713+ required: false ,
714+ secret: false ,
715+ description: None ,
716+ default : Some ( "info" . to_string( ) ) ,
717+ placeholder: None ,
718+ obtain_url: None ,
719+ obtain_instructions: None ,
720+ } ] ) ,
721+ publisher : None ,
722+ } ) ,
723+ } ;
724+
725+ let ( _, inputs) = entry. resolve_transport_and_inputs ( ) ;
726+
727+ assert_eq ! ( inputs. len( ) , 1 ) ;
728+ assert_eq ! ( inputs[ 0 ] . id, "LOG_LEVEL" ) ;
729+ assert_eq ! ( inputs[ 0 ] . default , Some ( "info" . to_string( ) ) ) ;
730+ // Should use explicit definition's type, not auto-discovered "password"
731+ assert_eq ! ( inputs[ 0 ] . r#type, "text" ) ;
732+ assert ! ( !inputs[ 0 ] . required) ;
733+ assert ! ( !inputs[ 0 ] . secret) ;
734+ }
735+
736+ #[ test]
737+ fn test_auto_discovered_inputs_have_no_default ( ) {
738+ let entry = UserServerEntry {
739+ command : Some ( "node" . to_string ( ) ) ,
740+ args : None ,
741+ env : Some ( HashMap :: from ( [ (
742+ "API_KEY" . to_string ( ) ,
743+ "${input:API_KEY}" . to_string ( ) ,
744+ ) ] ) ) ,
745+ url : None ,
746+ headers : None ,
747+ name : None ,
748+ description : None ,
749+ icon : None ,
750+ alias : None ,
751+ auth : None ,
752+ metadata : None ,
753+ } ;
754+
755+ let ( _, inputs) = entry. resolve_transport_and_inputs ( ) ;
756+
757+ assert_eq ! ( inputs. len( ) , 1 ) ;
758+ assert_eq ! ( inputs[ 0 ] . id, "API_KEY" ) ;
759+ assert_eq ! ( inputs[ 0 ] . default , None ) ;
760+ }
761+
762+ #[ test]
763+ fn test_input_default_serializes_roundtrip ( ) {
764+ let input = InputDefinition {
765+ id : "PORT" . to_string ( ) ,
766+ label : "Port" . to_string ( ) ,
767+ r#type : "number" . to_string ( ) ,
768+ required : false ,
769+ secret : false ,
770+ description : None ,
771+ default : Some ( "8080" . to_string ( ) ) ,
772+ placeholder : None ,
773+ obtain_url : None ,
774+ obtain_instructions : None ,
775+ } ;
776+
777+ let json = serde_json:: to_string ( & input) . unwrap ( ) ;
778+ let deserialized: InputDefinition = serde_json:: from_str ( & json) . unwrap ( ) ;
779+
780+ assert_eq ! ( deserialized. id, "PORT" ) ;
781+ assert_eq ! ( deserialized. default , Some ( "8080" . to_string( ) ) ) ;
782+ }
652783}
0 commit comments