1- using RestClient . Net . OpenApiGenerator ;
2-
31namespace RestClient . Net . McpGenerator ;
42
53internal readonly record struct McpParameterInfo (
@@ -20,14 +18,12 @@ internal static class McpToolGenerator
2018 /// <param name="namespace">The namespace for the MCP server.</param>
2119 /// <param name="serverName">The MCP server name.</param>
2220 /// <param name="extensionsNamespace">The namespace of the extensions.</param>
23- /// <param name="extensionsClassName">The class name of the extensions.</param>
2421 /// <returns>The generated MCP tools code.</returns>
2522 public static string GenerateTools (
2623 OpenApiDocument document ,
2724 string @namespace ,
2825 string serverName ,
29- string extensionsNamespace ,
30- string extensionsClassName
26+ string extensionsNamespace
3127 )
3228 {
3329 var tools = new List < string > ( ) ;
@@ -47,8 +43,6 @@ string extensionsClassName
4743 operation . Key ,
4844 operation . Value ,
4945 document . Components ? . Schemas ,
50- extensionsNamespace ,
51- extensionsClassName ,
5246 methodNameCounts
5347 ) ;
5448
@@ -71,6 +65,7 @@ string extensionsClassName
7165
7266 namespace {{ @namespace }} ;
7367
68+ /// <summary>MCP server tools for {{ serverName }} API.</summary>
7469 [McpServerToolType]
7570 public class {{ serverName }} Tools(IHttpClientFactory httpClientFactory)
7671 {
@@ -90,8 +85,6 @@ private static string GenerateTool(
9085 HttpMethod operationType ,
9186 OpenApiOperation operation ,
9287 IDictionary < string , IOpenApiSchema > ? schemas ,
93- string extensionsNamespace ,
94- string extensionsClassName ,
9588 Dictionary < string , int > methodNameCounts
9689 )
9790 {
@@ -123,7 +116,6 @@ Dictionary<string, int> methodNameCounts
123116 return GenerateToolMethod (
124117 mcpToolName ,
125118 extensionMethodName ,
126- extensionsClassName ,
127119 summary ,
128120 parameters ,
129121 hasBody ,
@@ -135,7 +127,6 @@ Dictionary<string, int> methodNameCounts
135127 private static string GenerateToolMethod (
136128 string toolName ,
137129 string extensionMethodName ,
138- string extensionsClassName ,
139130 string summary ,
140131 List < McpParameterInfo > parameters ,
141132 bool hasBody ,
@@ -177,6 +168,9 @@ string responseType
177168 ? string . Join ( ", " , extensionCallArgs ) + ", "
178169 : string . Empty ;
179170
171+ var okAlias = $ "Ok{ responseType } ";
172+ var errorAlias = $ "Error{ responseType } ";
173+
180174 return $$ """
181175 /// <summary>{{ SanitizeDescription ( summary ) }} </summary>
182176 {{ paramDescriptions }}
@@ -189,9 +183,9 @@ string responseType
189183
190184 return result switch
191185 {
192- Result< {{ responseType }} , HttpError<string>>.Ok (var success) =>
186+ {{ okAlias }} (var success) =>
193187 JsonSerializer.Serialize(success, JsonOptions),
194- Result< {{ responseType }} , HttpError<string>>.Error (var error) =>
188+ {{ errorAlias }} (var error) =>
195189 $"Error: {error.StatusCode} - {error.Body}",
196190 _ => "Unknown error"
197191 };
@@ -201,11 +195,13 @@ string responseType
201195
202196 private static string FormatParameter ( McpParameterInfo param )
203197 {
198+ var isNullable = param . Type . Contains ( '?' , StringComparison . Ordinal ) ;
199+
204200 var defaultPart =
205- param . DefaultValue != null
201+ isNullable ? " = null"
202+ : param . DefaultValue != null
206203 ? param . Type switch
207204 {
208- var t when t . Contains ( '?' , StringComparison . Ordinal ) => " = null" ,
209205 var t when t . StartsWith ( "string" , StringComparison . Ordinal ) =>
210206 $ " = \" { param . DefaultValue } \" ",
211207 var t when t . StartsWith ( "bool" , StringComparison . Ordinal ) =>
@@ -214,7 +210,6 @@ var t when t.StartsWith("bool", StringComparison.Ordinal) =>
214210 : " = false" ,
215211 _ => $ " = { param . DefaultValue } ",
216212 }
217- : param . Type . Contains ( '?' , StringComparison . Ordinal ) ? " = null"
218213 : string . Empty ;
219214
220215 return $ "{ param . Type } { param . Name } { defaultPart } ";
@@ -245,9 +240,31 @@ private static List<McpParameterInfo> GetParameters(
245240 var description = param . Description ?? sanitizedName ;
246241 var isPath = param . In == ParameterLocation . Path ;
247242 var isHeader = param . In == ParameterLocation . Header ;
243+ var isQuery = param . In == ParameterLocation . Query ;
244+
245+ // Extract default value - match the extension generator logic
246+ var rawDefaultValue = param . Schema ? . Default ? . ToString ( ) ;
247+ var isSimpleType =
248+ baseType
249+ is "string"
250+ or "int"
251+ or "long"
252+ or "float"
253+ or "double"
254+ or "decimal"
255+ or "bool" ;
256+ var defaultValue =
257+ isSimpleType && ! string . IsNullOrEmpty ( rawDefaultValue ) ? rawDefaultValue : null ;
258+
259+ // For optional string query parameters without a schema default, use empty string
260+ var hasNoDefault = defaultValue == null ;
261+ if ( ! required && baseType == "string" && isQuery && hasNoDefault )
262+ {
263+ defaultValue = "" ;
264+ }
248265
249- var defaultValue = param . Schema ? . Default ? . ToString ( ) ;
250- var makeNullable = ! required && defaultValue == null && ! baseType . EndsWith ( '?' ) ;
266+ // Make nullable if not required and no default value
267+ var makeNullable = ! required && hasNoDefault && ! baseType . EndsWith ( '?' ) ;
251268 var type = makeNullable ? $ "{ baseType } ?" : baseType ;
252269
253270 parameters . Add (
0 commit comments