Skip to main content
Glama

Azure MCP Server

Official
MIT License
1,161
  • Linux
  • Apple
SqlService.cs14.9 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System.Text.Json; using AzureMcp.Core.Options; using AzureMcp.Core.Services.Azure; using AzureMcp.Core.Services.Azure.Subscription; using AzureMcp.Core.Services.Azure.Tenant; using AzureMcp.Sql.Models; using AzureMcp.Sql.Services.Models; using Microsoft.Extensions.Logging; namespace AzureMcp.Sql.Services; public class SqlService(ISubscriptionService subscriptionService, ITenantService tenantService, ILogger<SqlService> logger) : BaseAzureResourceService(subscriptionService, tenantService), ISqlService { private readonly ILogger<SqlService> _logger = logger; /// <summary> /// Retrieves a specific SQL database from an Azure SQL Server. /// </summary> /// <param name="serverName">The name of the SQL server hosting the database</param> /// <param name="databaseName">The name of the database to retrieve</param> /// <param name="resourceGroup">The name of the resource group containing the server</param> /// <param name="subscription">The subscription ID or name</param> /// <param name="retryPolicy">Optional retry policy configuration for resilient operations</param> /// <param name="cancellationToken">Token to observe for cancellation requests</param> /// <returns>The SQL database if found, otherwise throws KeyNotFoundException</returns> /// <exception cref="KeyNotFoundException">Thrown when the specified database is not found</exception> /// <exception cref="ArgumentException">Thrown when required parameters are null or empty</exception> public async Task<SqlDatabase> GetDatabaseAsync( string serverName, string databaseName, string resourceGroup, string subscription, RetryPolicyOptions? retryPolicy, CancellationToken cancellationToken = default) { try { var result = await ExecuteSingleResourceQueryAsync( "Microsoft.Sql/servers/databases", resourceGroup, subscription, retryPolicy, ConvertToSqlDatabaseModel, $"name =~ '{EscapeKqlString(databaseName)}'", cancellationToken); if (result == null) { throw new KeyNotFoundException($"SQL database '{databaseName}' not found in resource group '{resourceGroup}' for subscription '{subscription}'."); } return result; } catch (Exception ex) { _logger.LogError(ex, "Error getting SQL database. Server: {Server}, Database: {Database}, ResourceGroup: {ResourceGroup}, Subscription: {Subscription}", serverName, databaseName, resourceGroup, subscription); throw; } } /// <summary> /// Retrieves a list of all SQL databases from an Azure SQL Server. /// </summary> /// <param name="serverName">The name of the SQL server to list databases from</param> /// <param name="resourceGroup">The name of the resource group containing the server</param> /// <param name="subscription">The subscription ID or name</param> /// <param name="retryPolicy">Optional retry policy configuration for resilient operations</param> /// <param name="cancellationToken">Token to observe for cancellation requests</param> /// <returns>A list of SQL databases on the specified server</returns> /// <exception cref="ArgumentException">Thrown when required parameters are null or empty</exception> public async Task<List<SqlDatabase>> ListDatabasesAsync( string serverName, string resourceGroup, string subscription, RetryPolicyOptions? retryPolicy, CancellationToken cancellationToken = default) { try { return await ExecuteResourceQueryAsync( "Microsoft.Sql/servers/databases", resourceGroup, subscription, retryPolicy, ConvertToSqlDatabaseModel, cancellationToken: cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "Error listing SQL databases. Server: {Server}, ResourceGroup: {ResourceGroup}, Subscription: {Subscription}", serverName, resourceGroup, subscription); throw; } } /// <summary> /// Retrieves a list of Microsoft Entra ID (formerly Azure AD) administrators for an Azure SQL Server. /// These administrators can authenticate to the SQL server using their Entra ID credentials. /// </summary> /// <param name="serverName">The name of the SQL server to get administrators for</param> /// <param name="resourceGroup">The name of the resource group containing the server</param> /// <param name="subscription">The subscription ID or name</param> /// <param name="retryPolicy">Optional retry policy configuration for resilient operations</param> /// <param name="cancellationToken">Token to observe for cancellation requests</param> /// <returns>A list of Entra ID administrators configured for the SQL server</returns> /// <exception cref="ArgumentException">Thrown when required parameters are null or empty</exception> public async Task<List<SqlServerEntraAdministrator>> GetEntraAdministratorsAsync( string serverName, string resourceGroup, string subscription, RetryPolicyOptions? retryPolicy, CancellationToken cancellationToken = default) { try { return await ExecuteResourceQueryAsync( "Microsoft.Sql/servers/administrators", resourceGroup, subscription, retryPolicy, ConvertToSqlServerEntraAdministratorModel, $"id contains '/servers/{EscapeKqlString(serverName)}/'", 50, cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "Error getting SQL server Entra ID administrators. Server: {Server}, ResourceGroup: {ResourceGroup}, Subscription: {Subscription}", serverName, resourceGroup, subscription); throw; } } /// <summary> /// Retrieves a list of elastic pools from an Azure SQL Server. /// Elastic pools provide a cost-effective solution for managing multiple databases with varying usage patterns. /// </summary> /// <param name="serverName">The name of the SQL server to get elastic pools from</param> /// <param name="resourceGroup">The name of the resource group containing the server</param> /// <param name="subscription">The subscription ID or name</param> /// <param name="retryPolicy">Optional retry policy configuration for resilient operations</param> /// <param name="cancellationToken">Token to observe for cancellation requests</param> /// <returns>A list of elastic pools configured on the SQL server</returns> /// <exception cref="ArgumentException">Thrown when required parameters are null or empty</exception> public async Task<List<SqlElasticPool>> GetElasticPoolsAsync( string serverName, string resourceGroup, string subscription, RetryPolicyOptions? retryPolicy, CancellationToken cancellationToken = default) { try { return await ExecuteResourceQueryAsync( "Microsoft.Sql/servers/elasticPools", resourceGroup, subscription, retryPolicy, ConvertToSqlElasticPoolModel, cancellationToken: cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "Error getting SQL elastic pools. Server: {Server}, ResourceGroup: {ResourceGroup}, Subscription: {Subscription}", serverName, resourceGroup, subscription); throw; } } /// <summary> /// Retrieves a list of firewall rules configured for an Azure SQL Server. /// Firewall rules control which IP addresses are allowed to connect to the SQL server. /// </summary> /// <param name="serverName">The name of the SQL server to get firewall rules for</param> /// <param name="resourceGroup">The name of the resource group containing the server</param> /// <param name="subscription">The subscription ID or name</param> /// <param name="retryPolicy">Optional retry policy configuration for resilient operations</param> /// <param name="cancellationToken">Token to observe for cancellation requests</param> /// <returns>A list of firewall rules configured on the SQL server</returns> /// <exception cref="ArgumentException">Thrown when required parameters are null or empty</exception> public async Task<List<SqlServerFirewallRule>> ListFirewallRulesAsync( string serverName, string resourceGroup, string subscription, RetryPolicyOptions? retryPolicy, CancellationToken cancellationToken = default) { try { return await ExecuteResourceQueryAsync( "Microsoft.Sql/servers/firewallRules", resourceGroup, subscription, retryPolicy, ConvertToSqlFirewallRuleModel, cancellationToken: cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "Error getting SQL server firewall rules. Server: {Server}, ResourceGroup: {ResourceGroup}, Subscription: {Subscription}", serverName, resourceGroup, subscription); throw; } } private static SqlDatabase ConvertToSqlDatabaseModel(JsonElement item) { SqlDatabaseData? sqlDatabase = SqlDatabaseData.FromJson(item); if (sqlDatabase == null) throw new InvalidOperationException("Failed to parse SQL database data"); return new SqlDatabase( Name: sqlDatabase.ResourceName ?? "Unknown", Id: sqlDatabase.ResourceId ?? "Unknown", Type: sqlDatabase.ResourceType ?? "Unknown", Location: sqlDatabase.Location, Sku: sqlDatabase.Sku != null ? new DatabaseSku( Name: sqlDatabase.Sku.Name, Tier: sqlDatabase.Sku.Tier, Capacity: sqlDatabase.Sku.Capacity, Family: sqlDatabase.Sku.Family, Size: sqlDatabase.Sku.Size ) : null, Status: sqlDatabase.Properties?.Status, Collation: sqlDatabase.Properties?.Collation, CreationDate: sqlDatabase.Properties?.CreatedOn, MaxSizeBytes: sqlDatabase.Properties?.MaxSizeBytes, ServiceLevelObjective: sqlDatabase.Properties?.CurrentServiceObjectiveName, Edition: sqlDatabase.Properties?.CurrentSku?.Name, ElasticPoolName: sqlDatabase.Properties?.ElasticPoolId?.ToString().Split('/').LastOrDefault(), EarliestRestoreDate: sqlDatabase.Properties?.EarliestRestoreOn, ReadScale: sqlDatabase.Properties?.ReadScale, ZoneRedundant: sqlDatabase.Properties?.IsZoneRedundant ); } private static SqlServerEntraAdministrator ConvertToSqlServerEntraAdministratorModel(JsonElement item) { SqlServerAadAdministratorData? admin = SqlServerAadAdministratorData.FromJson(item); if (admin == null) throw new InvalidOperationException("Failed to parse SQL server AAD administrator data"); return new SqlServerEntraAdministrator( Name: admin.ResourceName ?? "Unknown", Id: admin.ResourceId ?? "Unknown", Type: admin.ResourceType ?? "Unknown", AdministratorType: admin.Properties?.AdministratorType, Login: admin.Properties?.Login, Sid: admin.Properties?.Sid?.ToString(), TenantId: admin.Properties?.TenantId?.ToString(), AzureADOnlyAuthentication: admin.Properties?.IsAzureADOnlyAuthenticationEnabled ); } private static SqlElasticPool ConvertToSqlElasticPoolModel(JsonElement item) { SqlElasticPoolData? elasticPool = SqlElasticPoolData.FromJson(item); if (elasticPool == null) throw new InvalidOperationException("Failed to parse SQL elastic pool data"); return new SqlElasticPool( Name: elasticPool.ResourceName ?? "Unknown", Id: elasticPool.ResourceId ?? "Unknown", Type: elasticPool.ResourceType ?? "Unknown", Location: elasticPool.Location, Sku: elasticPool.Sku != null ? new ElasticPoolSku( Name: elasticPool.Sku.Name, Tier: elasticPool.Sku.Tier, Capacity: elasticPool.Sku.Capacity, Family: elasticPool.Sku.Family, Size: elasticPool.Sku.Size ) : null, State: elasticPool.Properties?.State, CreationDate: elasticPool.Properties?.CreatedOn, MaxSizeBytes: elasticPool.Properties?.MaxSizeBytes, PerDatabaseSettings: elasticPool.Properties?.PerDatabaseSettings != null ? new ElasticPoolPerDatabaseSettings( MinCapacity: elasticPool.Properties.PerDatabaseSettings.MinCapacity, MaxCapacity: elasticPool.Properties.PerDatabaseSettings.MaxCapacity ) : null, ZoneRedundant: elasticPool.Properties?.IsZoneRedundant, LicenseType: elasticPool.Properties?.LicenseType, DatabaseDtuMin: null, // DTU properties not available in current SDK DatabaseDtuMax: null, Dtu: null, StorageMB: null ); } private static SqlServerFirewallRule ConvertToSqlFirewallRuleModel(JsonElement item) { SqlFirewallRuleData? firewallRule = SqlFirewallRuleData.FromJson(item); if (firewallRule == null) throw new InvalidOperationException("Failed to parse SQL firewall rule data"); return new SqlServerFirewallRule( Name: firewallRule.ResourceName ?? "Unknown", Id: firewallRule.ResourceId ?? "Unknown", Type: firewallRule.ResourceType ?? "Unknown", StartIpAddress: firewallRule.Properties?.StartIPAddress, EndIpAddress: firewallRule.Properties?.EndIPAddress ); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Azure/azure-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server