Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 7 additions & 11 deletions docs/azmcp-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,13 @@ azmcp appconfig kv delete --subscription <subscription> \
--key <key> \
[--label <label>]

# List all key-value settings in an App Configuration store
azmcp appconfig kv list --subscription <subscription> \
--account <account> \
[--key <key>] \
[--label <label>]
# Get key-value settings in an App Configuration store
azmcp appconfig kv get --subscription <subscription> \
--account <account> \
[--key <key>] \
[--label <label>] \
[--key-filter <key-filter>] \
[--label-filter <label-filter>]

# Lock (make it read-only) or unlock (remove read-only) a key-value setting
azmcp appconfig kv lock set --subscription <subscription> \
Expand All @@ -294,12 +296,6 @@ azmcp appconfig kv set --subscription <subscription> \
--key <key> \
--value <value> \
[--label <label>]

# Show a specific key-value setting
azmcp appconfig kv show --subscription <subscription> \
--account <account> \
--key <key> \
[--label <label>]
```

### Azure App Lens Operations
Expand Down
7 changes: 4 additions & 3 deletions docs/e2eTestPrompts.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ This file contains prompts used for end-to-end testing to ensure each tool is in
| azmcp_appconfig_account_list | Show me the App Configuration stores in my subscription |
| azmcp_appconfig_account_list | Show me my App Configuration stores |
| azmcp_appconfig_kv_delete | Delete the key <key_name> in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_list | List all key-value settings in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_list | Show me the key-value settings in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_get | List all key-value settings in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_get | Show me the key-value settings in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_get | List all key-value settings with key name starting with 'prod-' in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_get | Show the content for the key <key_name> in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_lock_set | Lock the key <key_name> in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_lock_set | Unlock the key <key_name> in App Configuration store <app_config_store_name> |
| azmcp_appconfig_kv_set | Set the key <key_name> in App Configuration store <app_config_store_name> to \<value> |
| azmcp_appconfig_kv_show | Show the content for the key <key_name> in App Configuration store <app_config_store_name> |

## Azure App Lens

Expand Down
2 changes: 2 additions & 0 deletions servers/Azure.Mcp.Server/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ The Azure MCP Server updates automatically by default whenever a new release com

### Breaking Changes

- Merged `azmcp_appconfig_kv_list` and `azmcp_appconfig_kv_show` into `azmcp_appconfig_kv_get` which can handle both listing and filtering key-values and getting a specific key-value. [[#505](https://github.com/microsoft/mcp/pull/505)]

### Bugs Fixed

- Fixed the name of the Key Vault Managed HSM settings get command from `azmcp_keyvault_admin_get` to `azmcp_keyvault_admin_settings_get`. [[#643](https://github.com/microsoft/mcp/issues/643)]
Expand Down
11 changes: 4 additions & 7 deletions tools/Azure.Mcp.Tools.AppConfig/src/AppConfigSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ public void ConfigureServices(IServiceCollection services)

services.AddSingleton<AccountListCommand>();

services.AddSingleton<KeyValueListCommand>();
services.AddSingleton<KeyValueSetCommand>();
services.AddSingleton<KeyValueShowCommand>();
services.AddSingleton<KeyValueDeleteCommand>();
services.AddSingleton<KeyValueGetCommand>();
services.AddSingleton<KeyValueSetCommand>();

services.AddSingleton<KeyValueLockSetCommand>();
}
Expand All @@ -51,12 +50,10 @@ public CommandGroup RegisterCommands(IServiceProvider serviceProvider)

var keyValueDelete = serviceProvider.GetRequiredService<KeyValueDeleteCommand>();
keyValue.AddCommand(keyValueDelete.Name, keyValueDelete);
var keyValueList = serviceProvider.GetRequiredService<KeyValueListCommand>();
keyValue.AddCommand(keyValueList.Name, keyValueList);
var keyValueGet = serviceProvider.GetRequiredService<KeyValueGetCommand>();
keyValue.AddCommand(keyValueGet.Name, keyValueGet);
var keyValueSet = serviceProvider.GetRequiredService<KeyValueSetCommand>();
keyValue.AddCommand(keyValueSet.Name, keyValueSet);
var keyValueShow = serviceProvider.GetRequiredService<KeyValueShowCommand>();
keyValue.AddCommand(keyValueShow.Name, keyValueShow);

var keyValueLockSet = serviceProvider.GetRequiredService<KeyValueLockSetCommand>();
lockGroup.AddCommand(keyValueLockSet.Name, keyValueLockSet);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ namespace Azure.Mcp.Tools.AppConfig.Commands;

[JsonSerializable(typeof(AccountListCommand.AccountListCommandResult))]
[JsonSerializable(typeof(KeyValueDeleteCommand.KeyValueDeleteCommandResult))]
[JsonSerializable(typeof(KeyValueListCommand.KeyValueListCommandResult))]
[JsonSerializable(typeof(KeyValueGetCommand.KeyValueGetCommandResult))]
[JsonSerializable(typeof(KeyValueLockSetCommand.KeyValueLockSetCommandResult))]
[JsonSerializable(typeof(KeyValueShowCommand.KeyValueShowResult))]
[JsonSerializable(typeof(KeyValueSetCommand.KeyValueSetCommandResult))]
[JsonSerializable(typeof(AppConfigurationStoreData))]
[JsonSourceGenerationOptions(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Azure.Mcp.Core.Commands;
using Azure.Mcp.Core.Extensions;
using Azure.Mcp.Core.Models.Option;
using Azure.Mcp.Tools.AppConfig.Models;
using Azure.Mcp.Tools.AppConfig.Options;
using Azure.Mcp.Tools.AppConfig.Options.KeyValue;
using Azure.Mcp.Tools.AppConfig.Services;
using Microsoft.Extensions.Logging;

namespace Azure.Mcp.Tools.AppConfig.Commands.KeyValue;

public sealed class KeyValueGetCommand(ILogger<KeyValueGetCommand> logger) : BaseAppConfigCommand<KeyValueGetOptions>()
{
private const string CommandTitle = "Gets App Configuration Key-Value Settings";
private readonly ILogger<KeyValueGetCommand> _logger = logger;

public override string Name => "get";

public override string Description =>
"""
Gets key-values in an App Configuration store. This command can either retrieve a specific key-value by its key
and optional label, or list key-values if no key is provided. Listing key-values can optionally be filtered by a
key filter and label filter. Each key-value includes its key, value, label, content type, ETag, last modified time,
and lock status.
""";

public override string Title => CommandTitle;

public override ToolMetadata Metadata => new()
{
Destructive = false,
Idempotent = true,
OpenWorld = false,
ReadOnly = true,
LocalRequired = false,
Secret = false
};

protected override void RegisterOptions(Command command)
{
base.RegisterOptions(command);
command.Options.Add(AppConfigOptionDefinitions.Key.AsOptional());
command.Options.Add(AppConfigOptionDefinitions.Label);
command.Options.Add(AppConfigOptionDefinitions.KeyFilter);
command.Options.Add(AppConfigOptionDefinitions.LabelFilter);
command.Validators.Add(result =>
{
var key = result.GetValueOrDefault<string>(AppConfigOptionDefinitions.Key.Name);
var keyFilter = result.GetValueOrDefault(AppConfigOptionDefinitions.KeyFilter);
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(keyFilter))
{
result.AddError("Cannot specify both --key and --key-filter options together. Use only one to get a specific key-value or to filter the list of key-values.");
}
});
Comment thread
alzimmermsft marked this conversation as resolved.
}

protected override KeyValueGetOptions BindOptions(ParseResult parseResult)
{
var options = base.BindOptions(parseResult);
options.Key = parseResult.GetValueOrDefault<string>(AppConfigOptionDefinitions.Key.Name);
options.Label = parseResult.GetValueOrDefault<string>(AppConfigOptionDefinitions.Label.Name);
options.KeyFilter = parseResult.GetValueOrDefault<string>(AppConfigOptionDefinitions.KeyFilter.Name);
options.LabelFilter = parseResult.GetValueOrDefault<string>(AppConfigOptionDefinitions.LabelFilter.Name);
return options;
}

public override async Task<CommandResponse> ExecuteAsync(CommandContext context, ParseResult parseResult)
{
if (!Validate(parseResult.CommandResult, context.Response).IsValid)
{
return context.Response;
}

var options = BindOptions(parseResult);

try
{
var appConfigService = context.GetService<IAppConfigService>();
var settings = await appConfigService.GetKeyValues(
options.Account!,
options.Subscription!,
options.Key,
options.Label,
options.KeyFilter,
options.LabelFilter,
options.Tenant,
options.RetryPolicy);

context.Response.Results = ResponseResult.Create(new(settings ?? []), AppConfigJsonContext.Default.KeyValueGetCommandResult);
}
catch (Exception ex)
{
_logger.LogError("An exception occurred processing command. Exception: {Exception}", ex);
HandleException(context, ex);
}

return context.Response;
}

internal record KeyValueGetCommandResult(List<KeyValueSetting> Settings);
}

This file was deleted.

This file was deleted.

Loading