@@ -88,8 +88,7 @@ public class AggregateRecordsTool : IMcpTool
8888 ""orderby"": {
8989 ""type"": ""string"",
9090 ""enum"": [""asc"", ""desc""],
91- ""description"": ""Sort grouped results by the aggregated value. Requires groupby."",
92- ""default"": ""desc""
91+ ""description"": ""Sort direction for grouped results by the aggregated value. Only applies when groupby is provided; ignored otherwise.""
9392 },
9493 ""having"": {
9594 ""type"": ""object"",
@@ -394,23 +393,10 @@ public async Task<CallToolResult> ExecuteAsync(
394393 // Parse filter
395394 string ? filter = root . TryGetProperty ( "filter" , out JsonElement filterElement ) ? filterElement . GetString ( ) : null ;
396395
397- // Parse orderby
396+ // Parse orderby (validation deferred until after groupby is known;
397+ // if groupby is absent, orderby is silently ignored per #3279)
398398 bool userProvidedOrderby = root . TryGetProperty ( "orderby" , out JsonElement orderbyElement ) && ! string . IsNullOrWhiteSpace ( orderbyElement . GetString ( ) ) ;
399399 string orderby = "desc" ;
400- if ( userProvidedOrderby )
401- {
402- string normalizedOrderby = ( orderbyElement . GetString ( ) ?? string . Empty ) . Trim ( ) . ToLowerInvariant ( ) ;
403- if ( normalizedOrderby != "asc" && normalizedOrderby != "desc" )
404- {
405- return McpResponseBuilder . BuildErrorResult (
406- toolName ,
407- "InvalidArguments" ,
408- $ "Argument 'orderby' must be either 'asc' or 'desc' when provided. Got: '{ orderbyElement . GetString ( ) } '.",
409- logger ) ;
410- }
411-
412- orderby = normalizedOrderby ;
413- }
414400
415401 // Parse first
416402 int ? first = null ;
@@ -443,12 +429,28 @@ public async Task<CallToolResult> ExecuteAsync(
443429
444430 // Validate groupby-dependent parameters
445431 CallToolResult ? dependencyError = ValidateGroupByDependencies (
446- groupby . Count , userProvidedOrderby , first , after , toolName , logger ) ;
432+ groupby . Count , ref userProvidedOrderby , first , after , toolName , logger ) ;
447433 if ( dependencyError != null )
448434 {
449435 return dependencyError ;
450436 }
451437
438+ // Validate orderby value only when groupby is present (orderby is ignored otherwise)
439+ if ( userProvidedOrderby )
440+ {
441+ string normalizedOrderby = ( orderbyElement . GetString ( ) ?? string . Empty ) . Trim ( ) . ToLowerInvariant ( ) ;
442+ if ( normalizedOrderby != "asc" && normalizedOrderby != "desc" )
443+ {
444+ return McpResponseBuilder . BuildErrorResult (
445+ toolName ,
446+ "InvalidArguments" ,
447+ $ "Argument 'orderby' must be either 'asc' or 'desc' when provided. Got: '{ orderbyElement . GetString ( ) } '.",
448+ logger ) ;
449+ }
450+
451+ orderby = normalizedOrderby ;
452+ }
453+
452454 // Parse having clause
453455 Dictionary < string , double > ? havingOperators = null ;
454456 List < double > ? havingInValues = null ;
@@ -481,24 +483,24 @@ public async Task<CallToolResult> ExecuteAsync(
481483 }
482484
483485 /// <summary>
484- /// Validates that parameters requiring groupby (orderby, first, after) are only used when groupby is present.
486+ /// Validates that parameters requiring groupby (first, after) are only used when groupby is present.
485487 /// Also validates that 'after' requires 'first'.
488+ /// Note: 'orderby' without groupby is silently ignored rather than rejected (see #3279).
486489 /// </summary>
487- private static CallToolResult ? ValidateGroupByDependencies (
490+ internal static CallToolResult ? ValidateGroupByDependencies (
488491 int groupbyCount ,
489- bool userProvidedOrderby ,
492+ ref bool userProvidedOrderby ,
490493 int ? first ,
491494 string ? after ,
492495 string toolName ,
493496 ILogger ? logger )
494497 {
495498 if ( groupbyCount == 0 )
496499 {
497- if ( userProvidedOrderby )
498- {
499- return McpResponseBuilder . BuildErrorResult ( toolName , "InvalidArguments" ,
500- "The 'orderby' parameter requires 'groupby' to be specified. Sorting applies to grouped aggregation results." , logger ) ;
501- }
500+ // Silently ignore orderby when groupby is not provided.
501+ // LLMs may send orderby due to schema defaults; this is harmless
502+ // since ordering is meaningless without grouping.
503+ userProvidedOrderby = false ;
502504
503505 if ( first . HasValue )
504506 {
0 commit comments