diff --git a/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json b/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json index 8630cd28f1..a0959cccdb 100644 --- a/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json +++ b/core/Azure.Mcp.Core/src/Areas/Server/Resources/consolidated-tools.json @@ -2829,7 +2829,7 @@ } }, "mappedToolList": [ - "storagesync_cloudendpoint_triggerchangedetection" + "storagesync_cloudendpoint_changedetection" ] } ] diff --git a/servers/Azure.Mcp.Server/docs/azmcp-commands.md b/servers/Azure.Mcp.Server/docs/azmcp-commands.md index 4828d38d77..b2d9bc6342 100644 --- a/servers/Azure.Mcp.Server/docs/azmcp-commands.md +++ b/servers/Azure.Mcp.Server/docs/azmcp-commands.md @@ -2092,12 +2092,15 @@ azmcp storagesync cloudendpoint get --subscription \ [--name ] # Trigger change detection on a Cloud Endpoint +# ❌ Destructive | ❌ Idempotent | ❌ OpenWorld | ❌ ReadOnly | ❌ Secret | ❌ LocalRequired azmcp storagesync cloudendpoint changedetection --subscription \ --resource-group \ --service \ --syncgroup \ --name \ - [--directory-path ] + --directory-path \ + [--change-detection-mode ] \ + [--paths ...] ``` #### Registered Server diff --git a/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md b/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md index 695d2fda14..d71dfeb4af 100644 --- a/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md +++ b/servers/Azure.Mcp.Server/docs/e2eTestPrompts.md @@ -653,7 +653,7 @@ This file contains prompts used for end-to-end testing to ensure each tool is in | storagesync_syncgroup_create | Create a new sync group named in service | | storagesync_syncgroup_delete | Delete the sync group from service | | storagesync_syncgroup_get | Get the details of sync group in service | -| storagesync_cloudendpoint_changedetection | Trigger change detection on cloud endpoint in sync group in service | +| storagesync_cloudendpoint_changedetection | Trigger change detection on cloud endpoint in sync group in service for directory path | | storagesync_cloudendpoint_create | Create a new cloud endpoint named for Azure file share in storage account | | storagesync_cloudendpoint_delete | Delete the cloud endpoint from sync group | | storagesync_cloudendpoint_get | Get the details of cloud endpoint in sync group | diff --git a/tools/Azure.Mcp.Tools.StorageSync/src/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommand.cs b/tools/Azure.Mcp.Tools.StorageSync/src/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommand.cs index 4a3214c906..2a10119e01 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/src/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommand.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/src/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommand.cs @@ -22,7 +22,7 @@ public sealed class CloudEndpointTriggerChangeDetectionCommand(ILogger "96f096a2-d36f-4361-aa74-4e393e7f48a5"; - public override string Name => "triggerchangedetection"; + public override string Name => "changedetection"; public override string Description => "Trigger change detection on a cloud endpoint to sync file changes."; @@ -45,6 +45,9 @@ protected override void RegisterOptions(Command command) command.Options.Add(StorageSyncOptionDefinitions.StorageSyncService.Name.AsRequired()); command.Options.Add(StorageSyncOptionDefinitions.SyncGroup.Name.AsRequired()); command.Options.Add(StorageSyncOptionDefinitions.CloudEndpoint.Name.AsRequired()); + command.Options.Add(StorageSyncOptionDefinitions.CloudEndpoint.DirectoryPath.AsRequired()); + command.Options.Add(StorageSyncOptionDefinitions.CloudEndpoint.ChangeDetectionMode.AsOptional()); + command.Options.Add(StorageSyncOptionDefinitions.CloudEndpoint.Paths.AsOptional()); } protected override CloudEndpointTriggerChangeDetectionOptions BindOptions(ParseResult parseResult) @@ -54,6 +57,9 @@ protected override CloudEndpointTriggerChangeDetectionOptions BindOptions(ParseR options.StorageSyncServiceName = parseResult.GetValueOrDefault(StorageSyncOptionDefinitions.StorageSyncService.Name.Name); options.SyncGroupName = parseResult.GetValueOrDefault(StorageSyncOptionDefinitions.SyncGroup.Name.Name); options.CloudEndpointName = parseResult.GetValueOrDefault(StorageSyncOptionDefinitions.CloudEndpoint.Name.Name); + options.DirectoryPath = parseResult.GetValueOrDefault(StorageSyncOptionDefinitions.CloudEndpoint.DirectoryPath.Name); + options.ChangeDetectionMode = parseResult.GetValueOrDefault(StorageSyncOptionDefinitions.CloudEndpoint.ChangeDetectionMode.Name); + options.Paths = parseResult.GetValueOrDefault(StorageSyncOptionDefinitions.CloudEndpoint.Paths.Name)?.ToList(); return options; } @@ -68,8 +74,8 @@ public override async Task ExecuteAsync(CommandContext context, try { - _logger.LogInformation("Triggering change detection. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, ServiceName: {ServiceName}, GroupName: {GroupName}, EndpointName: {EndpointName}", - options.Subscription, options.ResourceGroup, options.StorageSyncServiceName, options.SyncGroupName, options.CloudEndpointName); + _logger.LogInformation("Triggering change detection. Subscription: {Subscription}, ResourceGroup: {ResourceGroup}, ServiceName: {ServiceName}, GroupName: {GroupName}, EndpointName: {EndpointName}, DirectoryPath: {DirectoryPath}, ChangeDetectionMode: {ChangeDetectionMode}", + options.Subscription, options.ResourceGroup, options.StorageSyncServiceName, options.SyncGroupName, options.CloudEndpointName, options.DirectoryPath, options.ChangeDetectionMode); await _service.TriggerChangeDetectionAsync( options.Subscription!, @@ -77,9 +83,9 @@ await _service.TriggerChangeDetectionAsync( options.StorageSyncServiceName!, options.SyncGroupName!, options.CloudEndpointName!, - null, - null, - false, + options.DirectoryPath!, + options.ChangeDetectionMode, + options.Paths, options.Tenant, options.RetryPolicy, cancellationToken); diff --git a/tools/Azure.Mcp.Tools.StorageSync/src/Options/CloudEndpoint/CloudEndpointTriggerChangeDetectionOptions.cs b/tools/Azure.Mcp.Tools.StorageSync/src/Options/CloudEndpoint/CloudEndpointTriggerChangeDetectionOptions.cs index b5c83d90f3..054962c812 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/src/Options/CloudEndpoint/CloudEndpointTriggerChangeDetectionOptions.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/src/Options/CloudEndpoint/CloudEndpointTriggerChangeDetectionOptions.cs @@ -22,4 +22,19 @@ public class CloudEndpointTriggerChangeDetectionOptions : BaseStorageSyncOptions /// Gets or sets the cloud endpoint name. /// public string? CloudEndpointName { get; set; } + + /// + /// Gets or sets the relative path to a directory Azure File share for which change detection is to be performed. + /// + public string? DirectoryPath { get; set; } + + /// + /// Gets or sets the change detection mode. Applies to a directory specified in directoryPath parameter. + /// + public string? ChangeDetectionMode { get; set; } + + /// + /// Gets or sets the array of relative paths on the Azure File share to be included in the change detection. Can be files and directories. + /// + public IList? Paths { get; set; } } diff --git a/tools/Azure.Mcp.Tools.StorageSync/src/Options/StorageSyncOptionDefinitions.cs b/tools/Azure.Mcp.Tools.StorageSync/src/Options/StorageSyncOptionDefinitions.cs index 105a59ffa6..89fbfed8c4 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/src/Options/StorageSyncOptionDefinitions.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/src/Options/StorageSyncOptionDefinitions.cs @@ -71,7 +71,8 @@ public static class CloudEndpoint private const string StorageAccountResourceIdName = "storage-account-resource-id"; private const string AzureFileShareNameName = "azure-file-share-name"; private const string DirectoryPathName = "directory-path"; - private const string RecursiveName = "recursive"; + private const string ChangeDetectionModeName = "change-detection-mode"; + private const string PathsName = "paths"; public static readonly Option Name = new($"--{NameName}", "-ce") { @@ -93,12 +94,18 @@ public static class CloudEndpoint public static readonly Option DirectoryPath = new($"--{DirectoryPathName}") { - Description = "The directory path for change detection" + Description = "Relative path to a directory on the Azure File share for which change detection is to be performed" }; - public static readonly Option Recursive = new($"--{RecursiveName}", "-r") + public static readonly Option ChangeDetectionMode = new($"--{ChangeDetectionModeName}") { - Description = "Recursively include subdirectories for change detection" + Description = "Change detection mode: 'Default' (directory only) or 'Recursive' (directory and subdirectories). Applies to the directory specified in directory-path" + }; + + public static readonly Option Paths = new($"--{PathsName}") + { + Description = "Array of relative paths on the Azure File share to be included in change detection. Can be files and directories", + AllowMultipleArgumentsPerToken = true }; } diff --git a/tools/Azure.Mcp.Tools.StorageSync/src/Services/IStorageSyncService.cs b/tools/Azure.Mcp.Tools.StorageSync/src/Services/IStorageSyncService.cs index 3023fc0156..42a5c48cba 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/src/Services/IStorageSyncService.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/src/Services/IStorageSyncService.cs @@ -190,9 +190,9 @@ Task TriggerChangeDetectionAsync( string storageSyncServiceName, string syncGroupName, string cloudEndpointName, - string? directoryPath = null, - string[]? filePaths = null, - bool recursive = false, + string directoryPath, + string? changeDetectionMode = null, + IList? paths = null, string? tenant = null, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); diff --git a/tools/Azure.Mcp.Tools.StorageSync/src/Services/StorageSyncService.cs b/tools/Azure.Mcp.Tools.StorageSync/src/Services/StorageSyncService.cs index 27c09915aa..fecf8f1fb0 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/src/Services/StorageSyncService.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/src/Services/StorageSyncService.cs @@ -626,9 +626,9 @@ public async Task TriggerChangeDetectionAsync( string storageSyncServiceName, string syncGroupName, string cloudEndpointName, - string? directoryPath = null, - string[]? filePaths = null, - bool recursive = false, + string directoryPath, + string? changeDetectionMode = null, + IList? paths = null, string? tenant = null, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) @@ -638,7 +638,8 @@ public async Task TriggerChangeDetectionAsync( (nameof(resourceGroup), resourceGroup), (nameof(storageSyncServiceName), storageSyncServiceName), (nameof(syncGroupName), syncGroupName), - (nameof(cloudEndpointName), cloudEndpointName) + (nameof(cloudEndpointName), cloudEndpointName), + (nameof(directoryPath), directoryPath) ); try @@ -653,13 +654,19 @@ public async Task TriggerChangeDetectionAsync( var content = new Azure.ResourceManager.StorageSync.Models.TriggerChangeDetectionContent { - DirectoryPath = directoryPath, - ChangeDetectionMode = recursive ? Azure.ResourceManager.StorageSync.Models.ChangeDetectionMode.Recursive : Azure.ResourceManager.StorageSync.Models.ChangeDetectionMode.Default + DirectoryPath = directoryPath }; - if (filePaths != null) + // Set change detection mode if provided + if (!string.IsNullOrEmpty(changeDetectionMode)) + { + content.ChangeDetectionMode = new Azure.ResourceManager.StorageSync.Models.ChangeDetectionMode(changeDetectionMode); + } + + // Add paths if provided + if (paths != null) { - foreach (var path in filePaths) + foreach (var path in paths) { content.Paths.Add(path); } diff --git a/tools/Azure.Mcp.Tools.StorageSync/src/StorageSyncSetup.cs b/tools/Azure.Mcp.Tools.StorageSync/src/StorageSyncSetup.cs index a615dff8f1..567b12bfdc 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/src/StorageSyncSetup.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/src/StorageSyncSetup.cs @@ -116,7 +116,7 @@ subscription access. cloudEndpointGroup.AddCommand("get", serviceProvider.GetRequiredService()); cloudEndpointGroup.AddCommand("create", serviceProvider.GetRequiredService()); cloudEndpointGroup.AddCommand("delete", serviceProvider.GetRequiredService()); - cloudEndpointGroup.AddCommand("triggerchangedetection", serviceProvider.GetRequiredService()); + cloudEndpointGroup.AddCommand("changedetection", serviceProvider.GetRequiredService()); // ServerEndpoint subgroup var serverEndpointGroup = new CommandGroup("serverendpoint", diff --git a/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/StorageSyncCommandTests.cs b/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/StorageSyncCommandTests.cs index a35582d8b4..f6f5d1201e 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/StorageSyncCommandTests.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/StorageSyncCommandTests.cs @@ -485,14 +485,17 @@ public async Task Should_Crud_endpoint() public async Task Should_trigger_cloud_endpoint_change_detection() { var result = await CallToolAsync( - "storagesync_cloudendpoint_triggerchangedetection", + "storagesync_cloudendpoint_changedetection", new() { { "subscription", Settings.SubscriptionId }, { "resource-group", Settings.ResourceGroupName }, { "name", Settings.ResourceBaseName }, { "sync-group-name", Settings.ResourceBaseName }, - { "cloud-endpoint-name", Settings.ResourceBaseName } + { "cloud-endpoint-name", Settings.ResourceBaseName }, + { "directory-path", "/" }, + { "change-detection-mode", "Recursive" }, + { "paths", new string[] { } } }); var message = result.AssertProperty("message"); diff --git a/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/assets.json b/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/assets.json index d85ad9f0e6..52dc179823 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/assets.json +++ b/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.LiveTests/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "", "TagPrefix": "Azure.Mcp.Tools.StorageSync.LiveTests", - "Tag": "Azure.Mcp.Tools.StorageSync.LiveTests_fd68071820" + "Tag": "Azure.Mcp.Tools.StorageSync.LiveTests_f467c63ce7" } diff --git a/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.UnitTests/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommandTests.cs b/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.UnitTests/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommandTests.cs index b0ed953547..89d24da33f 100644 --- a/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.UnitTests/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommandTests.cs +++ b/tools/Azure.Mcp.Tools.StorageSync/tests/Azure.Mcp.Tools.StorageSync.UnitTests/Commands/CloudEndpoint/CloudEndpointTriggerChangeDetectionCommandTests.cs @@ -27,13 +27,13 @@ public void Constructor_InitializesCommandCorrectly() { var command = _command.GetCommand(); Assert.NotNull(command); - Assert.Equal("triggerchangedetection", command.Name); + Assert.Equal("changedetection", command.Name); } [Fact] public void Name_ReturnsCorrectValue() { - Assert.Equal("triggerchangedetection", _command.Name); + Assert.Equal("changedetection", _command.Name); } }