From b63a13a3b0c78e27732bd5ece050c68f3b3b22ca Mon Sep 17 00:00:00 2001 From: Mansur Besleney Date: Tue, 20 Jan 2026 11:42:03 +0300 Subject: [PATCH] Refactor tool input schema handling and JSON serialization Set default 'Type' property in McpToolInputSchema and pass the schema object directly instead of building a dictionary. Use camelCase JSON serialization for input schemas in McpServerService to ensure correct property naming. --- .../Cli/Commands/Models/McpToolDefinition.cs | 1 + .../Cli/Commands/Services/McpServerService.cs | 36 +++++-------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Models/McpToolDefinition.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Models/McpToolDefinition.cs index 787b4e3802..f59776bc0a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Models/McpToolDefinition.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Models/McpToolDefinition.cs @@ -13,6 +13,7 @@ public class McpToolDefinition public class McpToolInputSchema { + public string Type { get; set; } = "object"; public Dictionary Properties { get; set; } public List Required { get; set; } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/McpServerService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/McpServerService.cs index 80fdcd3b7d..01c48a1345 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/McpServerService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/McpServerService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -18,6 +17,11 @@ public class McpServerService : ITransientDependency private const string LogSource = nameof(McpServerService); private const int MaxLogResponseLength = 500; + private static readonly JsonSerializerOptions JsonCamelCaseOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + private static class ToolErrorMessages { public const string InvalidResponseFormat = "The tool execution completed but returned an invalid response format. Please try again."; @@ -74,32 +78,8 @@ public class McpServerService : ITransientDependency private void RegisterToolFromDefinition(McpServerOptions options, McpToolDefinition toolDef) { - // Build input schema with lowercase keys as required by MCP JSON Schema format - var inputSchemaObject = new Dictionary - { - ["type"] = "object", - ["properties"] = ConvertProperties(toolDef.InputSchema?.Properties), - ["required"] = toolDef.InputSchema?.Required ?? new List() - }; - - RegisterTool(options, toolDef.Name, toolDef.Description, inputSchemaObject, toolDef.OutputSchema); - } - - private static Dictionary ConvertProperties(Dictionary properties) - { - if (properties == null) - { - return new Dictionary(); - } - - return properties.ToDictionary( - kvp => kvp.Key, - kvp => (object)new Dictionary - { - ["type"] = kvp.Value.Type, - ["description"] = kvp.Value.Description - } - ); + var inputSchema = toolDef.InputSchema ?? new McpToolInputSchema(); + RegisterTool(options, toolDef.Name, toolDef.Description, inputSchema, toolDef.OutputSchema); } private static CallToolResult CreateErrorResult(string errorMessage) @@ -132,7 +112,7 @@ public class McpServerService : ITransientDependency var tool = new AbpMcpServerTool( name, description, - JsonSerializer.SerializeToElement(inputSchema), + JsonSerializer.SerializeToElement(inputSchema, JsonCamelCaseOptions), outputSchema, (context, cancellationToken) => HandleToolInvocationAsync(name, context, cancellationToken) );