Skip to content
This repository was archived by the owner on Sep 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c7b0df6
Using ARG query to list & get Sql data
ArthurMa1978 Aug 11, 2025
a6f267e
update
ArthurMa1978 Aug 12, 2025
6348e68
update
ArthurMa1978 Aug 12, 2025
762f37d
update doc
ArthurMa1978 Aug 12, 2025
d856d23
update
ArthurMa1978 Aug 12, 2025
d57e70d
update
ArthurMa1978 Aug 12, 2025
9e1d572
update
ArthurMa1978 Aug 12, 2025
5aa0562
update
ArthurMa1978 Aug 13, 2025
eca7dd4
update
ArthurMa1978 Aug 13, 2025
f6856c6
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 13, 2025
57dd806
update
ArthurMa1978 Aug 13, 2025
a39d6bc
update
ArthurMa1978 Aug 13, 2025
e4e324a
update
ArthurMa1978 Aug 14, 2025
c6b4574
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 14, 2025
fe8ed38
update
ArthurMa1978 Aug 14, 2025
e588fad
revert vscode/README.md
ArthurMa1978 Aug 14, 2025
228ffc0
udpate
ArthurMa1978 Aug 14, 2025
a7c3c06
update
ArthurMa1978 Aug 15, 2025
b7d3879
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 15, 2025
0661eac
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 15, 2025
e391dab
update changelog
ArthurMa1978 Aug 15, 2025
84acd0b
update changelog
ArthurMa1978 Aug 15, 2025
54986bf
update checklist
ArthurMa1978 Aug 15, 2025
04b5116
Update the identify unused properteis check
ArthurMa1978 Aug 15, 2025
caecb2e
update
ArthurMa1978 Aug 15, 2025
631c25e
fix typo
ArthurMa1978 Aug 15, 2025
7f1cc08
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 18, 2025
9a5418e
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 19, 2025
3bdb737
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 19, 2025
4bd863c
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 20, 2025
67818a9
Merge branch 'main' into mgmt-sql
ArthurMa1978 Aug 20, 2025
c985dbe
update changelog
ArthurMa1978 Aug 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"cslschema",
"codeql",
"codesign",
"cutover",
"Commmand",
"Commitish",
"datatable",
Expand All @@ -113,6 +114,7 @@
"globaltool",
"glsl",
"Groq",
"Hyperscale",
"HKCU",
"HKEY_CURRENT_USER",
"hotmail",
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,22 @@ The Azure MCP Server updates automatically by default whenever a new release com

### Features Added

- Introduced `BaseAzureResourceService` class to perform Azure Resource read operations using Azure Resource Graph queries. [[#938](https://github.com/Azure/azure-mcp/pull/938)]
- Added support for listing Azure Function Apps via the command `azmcp-functionapp-list`. [[#863](https://github.com/Azure/azure-mcp/pull/863)]

### Breaking Changes

### Bugs Fixed

- Fixed SQL service test assertions to use case-insensitive string comparisons for resource type validation. [[#938](https://github.com/Azure/azure-mcp/pull/938)]
- Fixed HttpClient service test assertions to properly validate NoProxy collection handling instead of expecting a single string value. [[#938](https://github.com/Azure/azure-mcp/pull/938)]

### Other Changes

- Refactored SQL service implementation to use Azure Resource Graph queries instead of direct ARM API calls. [[#938](https://github.com/Azure/azure-mcp/pull/938)]
- Removed dependency on `Azure.ResourceManager.Sql` package by migrating to Azure Resource Graph queries, reducing package size and improving startup performance.
- Enhanced `BaseAzureService` with `EscapeKqlString` method for safe KQL query construction across all Azure services. [[#938](https://github.com/Azure/azure-mcp/pull/938)]
- Fixed KQL string escaping in Workbooks service queries.
- Refactored resource group option handling: introduced single global parser-optional `--resource-group` with declarative helpers `UseResourceGroup()` / `RequireResourceGroup()` and centralized logical validation & binding. Removed all area-specific optional resource group option definitions and manual per-command bindings; updated documentation to reflect new pattern.

#### Dependency Updates
Expand Down
1 change: 0 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
<PackageVersion Include="Azure.ResourceManager.Redis" Version="1.5.1" />
<PackageVersion Include="Azure.ResourceManager.RedisEnterprise" Version="1.2.1" />
<PackageVersion Include="Azure.ResourceManager.LoadTesting" Version="1.1.2" />
<PackageVersion Include="Azure.ResourceManager.Sql" Version="1.4.0-beta.3" />
<PackageVersion Include="Azure.Security.KeyVault.Keys" Version="4.7.0" />
<PackageVersion Include="Azure.Security.KeyVault.Secrets" Version="4.7.0" />
<PackageVersion Include="Azure.Security.KeyVault.Certificates" Version="4.7.0" />
Expand Down
1 change: 0 additions & 1 deletion areas/sql/src/AzureMcp.Sql/AzureMcp.Sql.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<ItemGroup />
<ItemGroup>
<PackageReference Include="Azure.ResourceManager" />
<PackageReference Include="Azure.ResourceManager.Sql" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="ModelContextProtocol" />
<PackageReference Include="System.CommandLine" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,6 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,
options.Subscription!,
options.RetryPolicy);

if (database == null)
{
context.Response.Status = 404;
context.Response.Message = $"Database '{options.Database}' not found on server '{options.Server}' in resource group '{options.ResourceGroup}'.";
return context.Response;
}

context.Response.Results = ResponseResult.Create(
new DatabaseShowResult(database),
SqlJsonContext.Default.DatabaseShowResult);
Expand All @@ -77,6 +70,7 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,

protected override string GetErrorMessage(Exception ex) => ex switch
{
KeyNotFoundException => $"SQL database not found. Verify the database name, server name, resource group, and that you have access.",
Azure.RequestFailedException reqEx when reqEx.Status == 404 =>
"Database or server not found. Verify the database name, server name, resource group, and that you have access.",
Azure.RequestFailedException reqEx when reqEx.Status == 403 =>
Expand All @@ -87,6 +81,7 @@ public override async Task<CommandResponse> ExecuteAsync(CommandContext context,

protected override int GetStatusCode(Exception ex) => ex switch
{
KeyNotFoundException => 404,
Azure.RequestFailedException reqEx => reqEx.Status,
_ => base.GetStatusCode(ex)
};
Expand Down
5 changes: 5 additions & 0 deletions areas/sql/src/AzureMcp.Sql/Commands/SqlJsonContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using AzureMcp.Sql.Commands.EntraAdmin;
using AzureMcp.Sql.Commands.FirewallRule;
using AzureMcp.Sql.Models;
using AzureMcp.Sql.Services.Models;

namespace AzureMcp.Sql.Commands;

Expand All @@ -22,6 +23,10 @@ namespace AzureMcp.Sql.Commands;
[JsonSerializable(typeof(DatabaseSku))]
[JsonSerializable(typeof(ElasticPoolSku))]
[JsonSerializable(typeof(ElasticPoolPerDatabaseSettings))]
[JsonSerializable(typeof(SqlDatabaseData))]
[JsonSerializable(typeof(SqlServerAadAdministratorData))]
[JsonSerializable(typeof(SqlElasticPoolData))]
[JsonSerializable(typeof(SqlFirewallRuleData))]
[JsonSourceGenerationOptions(
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
WriteIndented = true,
Expand Down
5 changes: 3 additions & 2 deletions areas/sql/src/AzureMcp.Sql/Services/ISqlService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ public interface ISqlService
/// <param name="subscription">The subscription ID or name</param>
/// <param name="retryPolicy">Optional retry policy options</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>The SQL database information, or null if not found</returns>
Task<SqlDatabase?> GetDatabaseAsync(
/// <returns>The SQL database information</returns>
/// <exception cref="KeyNotFoundException">Thrown when the database is not found</exception>
Task<SqlDatabase> GetDatabaseAsync(
string serverName,
string databaseName,
string resourceGroup,
Expand Down
19 changes: 19 additions & 0 deletions areas/sql/src/AzureMcp.Sql/Services/Models/DatabaseIdentity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Text.Json.Serialization;

namespace AzureMcp.Sql.Services.Models
{
/// <summary> Azure Active Directory identity configuration for a resource. </summary>
internal sealed class DatabaseIdentity
{
/// <summary> The identity type. </summary>
[JsonPropertyName("type")]
public string? IdentityType { get; set; }
/// <summary> The Azure Active Directory tenant id. </summary>
public Guid? TenantId { get; set; }
/// <summary> The resource ids of the user assigned identities to use. </summary>
public IDictionary<string, SqlUserAssignedIdentity>? UserAssignedIdentities { get; set; }
}
}
46 changes: 46 additions & 0 deletions areas/sql/src/AzureMcp.Sql/Services/Models/SqlDatabaseData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Text.Json;
using System.Text.Json.Serialization;
using AzureMcp.Sql.Commands;

namespace AzureMcp.Sql.Services.Models
{
/// <summary>
/// A class representing the SqlDatabase data model.
/// A database resource.
/// </summary>
internal sealed class SqlDatabaseData
{
/// <summary> The resource ID for the resource. </summary>
[JsonPropertyName("id")]
public string? ResourceId { get; set; }
/// <summary> The type of the resource. </summary>
[JsonPropertyName("type")]
public string? ResourceType { get; set; }
/// <summary> The name of the resource. </summary>
[JsonPropertyName("name")]
public string? ResourceName { get; set; }
/// <summary> The location of the resource. </summary>
public string? Location { get; set; }
/// <summary> The database SKU. </summary>
public SqlSku? Sku { get; set; }
/// <summary> Kind of database. This is metadata used for the Azure portal experience. </summary>
public string? Kind { get; set; }
/// <summary> Resource that manages the database. </summary>
public string? ManagedBy { get; set; }
/// <summary> The Azure Active Directory identity of the database. </summary>
public DatabaseIdentity? Identity { get; set; }
/// <summary> The tags of the resource. </summary>
public IDictionary<string, string>? Tags { get; set; }
/// <summary> Properties of the Sql database. </summary>
public SqlDatabaseProperties? Properties { get; set; }

// Read the JSON response content and create a model instance from it.
public static SqlDatabaseData? FromJson(JsonElement source)
{
return JsonSerializer.Deserialize<SqlDatabaseData>(source, SqlJsonContext.Default.SqlDatabaseData);
}
}
}
24 changes: 24 additions & 0 deletions areas/sql/src/AzureMcp.Sql/Services/Models/SqlDatabaseKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Text.Json.Serialization;

namespace AzureMcp.Sql.Services.Models
{
/// <summary> Database level key used for encryption at rest. </summary>
internal sealed class SqlDatabaseKey
{
/// <summary> The database key type. Only supported value is 'AzureKeyVault'. </summary>
[JsonPropertyName("type")]
public string? KeyType { get; set; }
/// <summary> Thumbprint of the database key. </summary>
public string? Thumbprint { get; set; }
/// <summary> The database key creation date. </summary>
[JsonPropertyName("creationDate")]
public DateTimeOffset? CreatedOn { get; set; }
/// <summary> Subregion of the server key. </summary>
public string? Subregion { get; set; }
/// <summary> The database key's version. </summary>
public string? KeyVersion { get; set; }
}
}
Loading
Loading