From 1524f97739e5c573a7fefa35c9991f5fe2fda797 Mon Sep 17 00:00:00 2001 From: "Yun Liu (from Dev Box)" Date: Tue, 19 May 2026 15:38:29 +1000 Subject: [PATCH 1/3] Enhance error handling in AzApiDocsService and update status code in AzApiDocsGetCommandTests --- .../src/Commands/AzApiDocsGetCommand.cs | 7 +++++++ .../src/Services/AzApiDocsService.cs | 14 +++++++++++++- .../AzApiDocsGetCommandTests.cs | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/Azure.Mcp.Tools.AzureTerraform/src/Commands/AzApiDocsGetCommand.cs b/tools/Azure.Mcp.Tools.AzureTerraform/src/Commands/AzApiDocsGetCommand.cs index 04b416f5a3..0368b092a7 100644 --- a/tools/Azure.Mcp.Tools.AzureTerraform/src/Commands/AzApiDocsGetCommand.cs +++ b/tools/Azure.Mcp.Tools.AzureTerraform/src/Commands/AzApiDocsGetCommand.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.IO; using System.Net; using Azure.Mcp.Tools.AzureTerraform.Models; using Azure.Mcp.Tools.AzureTerraform.Options; @@ -55,6 +56,12 @@ protected override AzApiDocsOptions BindOptions(ParseResult parseResult) }; } + protected override HttpStatusCode GetStatusCode(Exception ex) => ex switch + { + InvalidDataException => HttpStatusCode.BadRequest, + _ => base.GetStatusCode(ex) + }; + public override async Task ExecuteAsync( CommandContext context, ParseResult parseResult, diff --git a/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs b/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs index 4920c33562..bc8816b13c 100644 --- a/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs +++ b/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs @@ -21,7 +21,19 @@ public sealed class AzApiDocsService : IAzApiDocsService public AzApiDocsResult GetDocumentation(string resourceTypeName, string? apiVersion = null) { var serviceProvider = s_schemaServiceProvider.Value; - TypesDefinitionResult typesResult = SchemaGenerator.GetResourceTypeDefinitions(serviceProvider, resourceTypeName, apiVersion); + TypesDefinitionResult typesResult; + try + { + typesResult = SchemaGenerator.GetResourceTypeDefinitions(serviceProvider, resourceTypeName, apiVersion); + } + catch (InvalidDataException) + { + throw; + } + catch (Exception ex) + { + throw new InvalidDataException(ex.Message, ex); + } List complexTypes = SchemaGenerator.GetResponse(typesResult); string resolvedApiVersion = typesResult.ApiVersion; diff --git a/tools/Azure.Mcp.Tools.AzureTerraform/tests/Azure.Mcp.Tools.AzureTerraform.Tests/AzApiDocsGetCommandTests.cs b/tools/Azure.Mcp.Tools.AzureTerraform/tests/Azure.Mcp.Tools.AzureTerraform.Tests/AzApiDocsGetCommandTests.cs index cdb65e5222..ae05690efd 100644 --- a/tools/Azure.Mcp.Tools.AzureTerraform/tests/Azure.Mcp.Tools.AzureTerraform.Tests/AzApiDocsGetCommandTests.cs +++ b/tools/Azure.Mcp.Tools.AzureTerraform/tests/Azure.Mcp.Tools.AzureTerraform.Tests/AzApiDocsGetCommandTests.cs @@ -136,7 +136,7 @@ public async Task ExecuteAsync_ServiceThrows_HandlesException() var response = await ExecuteCommandAsync("--resource-type", "Microsoft.Fake/nonexistent"); - Assert.NotEqual(HttpStatusCode.OK, response.Status); + Assert.Equal(HttpStatusCode.BadRequest, response.Status); } [Theory] From 5216f20703eb47453626e9588def5435b8d85cab Mon Sep 17 00:00:00 2001 From: "Yun Liu (from Dev Box)" Date: Tue, 19 May 2026 15:50:48 +1000 Subject: [PATCH 2/3] Add changelog entry for azapi_get 400 BadRequest fix --- .../changelog-entries/yunliu1-azapi-get-bad-request.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 servers/Azure.Mcp.Server/changelog-entries/yunliu1-azapi-get-bad-request.yaml diff --git a/servers/Azure.Mcp.Server/changelog-entries/yunliu1-azapi-get-bad-request.yaml b/servers/Azure.Mcp.Server/changelog-entries/yunliu1-azapi-get-bad-request.yaml new file mode 100644 index 0000000000..fe8afd1721 --- /dev/null +++ b/servers/Azure.Mcp.Server/changelog-entries/yunliu1-azapi-get-bad-request.yaml @@ -0,0 +1,3 @@ +changes: + - section: "Bugs Fixed" + description: "Fixed `azureterraform_azapi_get` returning `500 InternalServerError` for invalid resource type or API version inputs. The tool now returns `400 BadRequest` with an actionable message, enabling agents to auto-correct and retry with valid inputs." From 527d6f0b17fed22c8915e8543a712c1c184388f3 Mon Sep 17 00:00:00 2001 From: vcolin7 Date: Tue, 9 Jun 2026 17:34:35 -0700 Subject: [PATCH 3/3] Change `GetResourceApiVersions.ResourceVisitor` in BicepSchema tools to throw `InvalidDataException` for unknown resource types (#2840) Change `GetResourceApiVersions.ResourceVisitor` in the BicepSchema tools to throw `InvalidDataException` for unknown resource types `GetResourceApiVersions` threw a bare `Exception` (and an unhandled `KeyNotFoundException` when the provider existed but the resource type did not), which `AzApiDocsService` normalized via a broad catch-all that also misclassified real server-side faults as `400 BadRequest`. Throw `InvalidDataException` at the source instead, consistent with `LoadSingleResource`, and drop the catch-all so unexpected exceptions surface as `500`. --- .../src/Services/AzApiDocsService.cs | 14 +------------- .../Services/ResourceProperties/ResourceVisitor.cs | 7 ++++--- .../GetSchemaTests.cs | 2 +- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs b/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs index bc8816b13c..4920c33562 100644 --- a/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs +++ b/tools/Azure.Mcp.Tools.AzureTerraform/src/Services/AzApiDocsService.cs @@ -21,19 +21,7 @@ public sealed class AzApiDocsService : IAzApiDocsService public AzApiDocsResult GetDocumentation(string resourceTypeName, string? apiVersion = null) { var serviceProvider = s_schemaServiceProvider.Value; - TypesDefinitionResult typesResult; - try - { - typesResult = SchemaGenerator.GetResourceTypeDefinitions(serviceProvider, resourceTypeName, apiVersion); - } - catch (InvalidDataException) - { - throw; - } - catch (Exception ex) - { - throw new InvalidDataException(ex.Message, ex); - } + TypesDefinitionResult typesResult = SchemaGenerator.GetResourceTypeDefinitions(serviceProvider, resourceTypeName, apiVersion); List complexTypes = SchemaGenerator.GetResponse(typesResult); string resolvedApiVersion = typesResult.ApiVersion; diff --git a/tools/Azure.Mcp.Tools.BicepSchema/src/Services/ResourceProperties/ResourceVisitor.cs b/tools/Azure.Mcp.Tools.BicepSchema/src/Services/ResourceProperties/ResourceVisitor.cs index e31b5a63ac..1471eab722 100644 --- a/tools/Azure.Mcp.Tools.BicepSchema/src/Services/ResourceProperties/ResourceVisitor.cs +++ b/tools/Azure.Mcp.Tools.BicepSchema/src/Services/ResourceProperties/ResourceVisitor.cs @@ -86,12 +86,13 @@ public string[] GetResourceApiVersions(string resourceTypeName) { (string providerName, _, _) = ResourceParser.ParseResourceType(resourceTypeName); - if (!GetAllResourceTypesAndVersionsByProvider().TryGetValue(providerName, out ProviderResourceTypes? provider)) + if (!GetAllResourceTypesAndVersionsByProvider().TryGetValue(providerName, out ProviderResourceTypes? provider) + || !provider.ResourceTypes.TryGetValue(resourceTypeName.ToLowerInvariant(), out UniqueResourceType? uniqueResourceType)) { - throw new Exception($"Resource type {resourceTypeName} not found."); + throw new InvalidDataException($"Resource type {resourceTypeName} not found."); } - return [.. provider.ResourceTypes[resourceTypeName.ToLowerInvariant()].ApiVersions]; + return [.. uniqueResourceType.ApiVersions]; } public TypesDefinitionResult LoadSingleResource(string resourceTypeName, string apiVersion) diff --git a/tools/Azure.Mcp.Tools.BicepSchema/tests/Azure.Mcp.Tools.BicepSchema.Tests/GetSchemaTests.cs b/tools/Azure.Mcp.Tools.BicepSchema/tests/Azure.Mcp.Tools.BicepSchema.Tests/GetSchemaTests.cs index 2a9188f864..67f467bb21 100644 --- a/tools/Azure.Mcp.Tools.BicepSchema/tests/Azure.Mcp.Tools.BicepSchema.Tests/GetSchemaTests.cs +++ b/tools/Azure.Mcp.Tools.BicepSchema/tests/Azure.Mcp.Tools.BicepSchema.Tests/GetSchemaTests.cs @@ -33,7 +33,7 @@ public void GetResourcePropertySchema_ShouldThrowOnNotFound() SchemaGenerator.ConfigureServices(serviceCollection); IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - var exception = Assert.Throws(() => + var exception = Assert.Throws(() => { TypesDefinitionResult result = SchemaGenerator.GetResourceTypeDefinitions(serviceProvider, "Microsoft.Unknown/virtualRandom"); _ = SchemaGenerator.GetResponse(result);