diff --git a/core/Microsoft.Mcp.Core/src/Commands/BaseCommand`2.cs b/core/Microsoft.Mcp.Core/src/Commands/BaseCommand`2.cs index cafdbecdaa..d4fc94b9a2 100644 --- a/core/Microsoft.Mcp.Core/src/Commands/BaseCommand`2.cs +++ b/core/Microsoft.Mcp.Core/src/Commands/BaseCommand`2.cs @@ -121,15 +121,8 @@ protected virtual void HandleException(CommandContext context, Exception ex) if (ex is CommandValidationException cve) { response.Status = cve.StatusCode; - // If specific missing options are provided, format a consistent message - if (cve.MissingOptions is { Count: > 0 }) - { - response.Message = $"{MissingRequiredOptionsPrefix}{string.Join(", ", cve.MissingOptions)}"; - } - else - { - response.Message = cve.Message; - } + response.Message = cve.Message; + // Include the command validation exception message as it should be safe. Requires custom validators to // exclude any sensitive information from their error messages. context.Activity?.SetTag(TagName.ExceptionMessage, response.Message); diff --git a/core/Microsoft.Mcp.Core/src/Options/OptionAttribute.cs b/core/Microsoft.Mcp.Core/src/Options/OptionAttribute.cs index 5d96f8d662..7b96ac86f4 100644 --- a/core/Microsoft.Mcp.Core/src/Options/OptionAttribute.cs +++ b/core/Microsoft.Mcp.Core/src/Options/OptionAttribute.cs @@ -18,22 +18,6 @@ namespace Microsoft.Mcp.Core.Options; [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] public sealed class OptionAttribute : Attribute { - /// - /// Initializes a new instance with default values. - /// Use named properties to override: [Option(Name = "x", Description = "y", Hidden = true)]. - /// - public OptionAttribute() { } - - /// - /// Initializes a new instance with a description. - /// Shorthand for [Option(Description = "...")]. - /// - /// A description of what the option controls. - public OptionAttribute(string description) - { - Description = description; - } - /// /// Override the CLI option name (without the "--" prefix). /// When null, the name is derived from the property name in kebab-case. @@ -48,7 +32,7 @@ public OptionAttribute(string description) /// /// A description of what the option controls. Used in help text and by AI agents. /// - public string? Description { get; init; } + public required string Description { get; init; } /// /// A default value for the option when a value is not provided. Must match the property type being attributed. @@ -56,7 +40,12 @@ public OptionAttribute(string description) public object? DefaultValue { get; init; } /// - /// Whether the option is hidden from help output. + /// Whether the option is hidden from help output. Default is false. + /// + public bool Hidden { get; init; } = false; + + /// + /// Whether the option allows an empty or whitespace-only string as a valid value. Default handling is to reject such values. /// - public bool Hidden { get; init; } + public bool AllowEmptyOrWhiteSpaceString { get; init; } = false; } diff --git a/core/Microsoft.Mcp.Core/src/Options/OptionBinder.cs b/core/Microsoft.Mcp.Core/src/Options/OptionBinder.cs index 6591abeb60..74a557bed4 100644 --- a/core/Microsoft.Mcp.Core/src/Options/OptionBinder.cs +++ b/core/Microsoft.Mcp.Core/src/Options/OptionBinder.cs @@ -51,7 +51,7 @@ public static class OptionBinder { var instance = (TOptions)CreateInstance(typeof(TOptions)); List missingOptions = []; - List errors = []; + List errors = [.. parseResult.Errors.Select(e => e.Message)]; Dictionary? parentInstances = null; var handlers = s_optionTypeHandlers.GetOrAdd(typeof(TOptions), _ => GetOptionTypeHandlers()); diff --git a/core/Microsoft.Mcp.Core/src/Options/OptionContainerAttribute.cs b/core/Microsoft.Mcp.Core/src/Options/OptionContainerAttribute.cs new file mode 100644 index 0000000000..95714c02be --- /dev/null +++ b/core/Microsoft.Mcp.Core/src/Options/OptionContainerAttribute.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Microsoft.Mcp.Core.Options; + +/// +/// Attribute for complex option containers (aka, classes that are used in option definitions that contain options themselves). +/// +/// Properties with this attribute must be complex types that contain other options. +/// +/// +[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)] +public sealed class OptionContainerAttribute : Attribute +{ + /// + /// The prefix to use for the options in the container. + /// If null, the property name (in kebab-case) is used as the prefix. + /// + /// For example, if the property is named "Vault" and the prefix is "v", the options in the container will be prefixed with "--v-". + /// If the property is named "Vault" and the prefix is null, the options in the container will be prefixed with "--vault-". + /// + /// + public string? Prefix { get; init; } +} diff --git a/core/Microsoft.Mcp.Core/src/Options/OptionDescriptor.cs b/core/Microsoft.Mcp.Core/src/Options/OptionDescriptor.cs index d63ba6b3b6..e3be42b52d 100644 --- a/core/Microsoft.Mcp.Core/src/Options/OptionDescriptor.cs +++ b/core/Microsoft.Mcp.Core/src/Options/OptionDescriptor.cs @@ -11,10 +11,11 @@ public class OptionDescriptor { public required string Name { get; init; } public required string Description { get; init; } - public string[] Aliases { get; init; } = []; + public required string[] Aliases { get; init; } public bool Required { get; init; } public bool Hidden { get; init; } public object? DefaultValue { get; init; } + public bool AllowEmptyOrWhiteSpaceString { get; init; } public required PropertyInfo TargetProperty { get; init; } public required Type Type { get; init; } public PropertyInfo? ParentProperty { get; init; } @@ -22,14 +23,19 @@ public class OptionDescriptor public static OptionDescriptor[] FromType<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>() where T : class { List optionDescriptors = []; - NullabilityInfoContext nullabilityContext = new(); - CollectDescriptors(typeof(T), prefix: null, optionDescriptors, nullabilityContext); + CollectDescriptors(typeof(T), null, optionDescriptors, new(), true, null); return [.. optionDescriptors]; } [UnconditionalSuppressMessage("Trimming", "IL2070:UnrecognizedReflectionPattern", Justification = "Nested option types are rooted by the application.")] - private static void CollectDescriptors(Type type, string? prefix, List descriptors, NullabilityInfoContext nullabilityContext, bool parentRequired = true, PropertyInfo? parentProperty = null) + private static void CollectDescriptors( + Type type, + string? prefix, + List descriptors, + NullabilityInfoContext nullabilityContext, + bool parentRequired, + PropertyInfo? parentProperty) { PropertyInfo[] allProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); @@ -53,28 +59,27 @@ private static void CollectDescriptors(Type type, string? prefix, List(); - // Only include properties with [Option] - if (optionAttribute == null) + var optionAttribute = property.GetCustomAttribute(); + var optionContainerAttribute = property.GetCustomAttribute(); + // Only include properties with [Option] or [OptionContainer] + if (optionAttribute == null && optionContainerAttribute == null) { continue; } - string name = optionAttribute?.Name ?? OptionNameConvention.ToKebabCase(property.Name); - - if (!string.IsNullOrEmpty(prefix)) + if (optionAttribute != null && optionContainerAttribute != null) { - name = $"{prefix}-{name}"; + throw new InvalidOperationException("Properties can only be attributed with [Option] or [OptionContainer], not both."); } var required = Attribute.IsDefined(property, typeof(RequiredMemberAttribute)); - if (IsComplexType(property.PropertyType)) - { - // Flatten nested complex types with a prefix. - CollectDescriptors(property.PropertyType, name, descriptors, nullabilityContext, parentRequired: required, parentProperty: property); - } - else + var complex = IsComplexType(property.PropertyType); + if (optionAttribute != null) { + if (complex) + { + throw new InvalidOperationException("Complex properties cannot use [Option] attribute. Use [OptionContainer] instead."); + } if (!parentRequired && required) { throw new InvalidOperationException( @@ -86,24 +91,45 @@ private static void CollectDescriptors(Type type, string? prefix, List public sealed class ResourceDiagnoseOptions { - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option("Azure resource group name. Provide this when disambiguating between multiple resources of the same name.")] + [Option(Description = "Azure resource group name. Provide this when disambiguating between multiple resources of the same name.")] public string? ResourceGroup { get; set; } /// /// The user's question for diagnosis. /// - [Option("User question")] + [Option(Description = "User question")] public required string Question { get; set; } /// /// The name of the resource to diagnose. /// - [Option("The name of the resource to investigate or diagnose")] + [Option(Description = "The name of the resource to investigate or diagnose")] public required string Resource { get; set; } /// /// The Resource Type of the resource to diagnose. This is optional and used to disambiguate between multiple resources with the same name. /// - [Option("Resource type. Provide this when disambiguating between multiple resources of the same name.")] + [Option(Description = "Resource type. Provide this when disambiguating between multiple resources of the same name.")] public string? ResourceType { get; set; } /// /// The subscription of the resource to diagnose. This is optional and used to disambiguate between multiple resources with the same name. /// - [Option("Azure subscription ID or name. Provide this when disambiguating between multiple resources of the same name.")] + [Option(Description = "Azure subscription ID or name. Provide this when disambiguating between multiple resources of the same name.")] public string? Subscription { get; set; } } diff --git a/tools/Azure.Mcp.Tools.ApplicationInsights/src/Options/RecommendationListOptions.cs b/tools/Azure.Mcp.Tools.ApplicationInsights/src/Options/RecommendationListOptions.cs index 0c4de4c239..0f18266918 100644 --- a/tools/Azure.Mcp.Tools.ApplicationInsights/src/Options/RecommendationListOptions.cs +++ b/tools/Azure.Mcp.Tools.ApplicationInsights/src/Options/RecommendationListOptions.cs @@ -8,15 +8,15 @@ namespace Azure.Mcp.Tools.ApplicationInsights.Options; public class RecommendationListOptions : ISubscriptionOption { - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.ResourceGroup)] + [Option(Description = OptionDescriptions.ResourceGroup)] public string? ResourceGroup { get; set; } - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseClusterCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseClusterCommand.cs index 53e35aac8d..cbf7df1d21 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseClusterCommand.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseClusterCommand.cs @@ -33,7 +33,7 @@ public override void ValidateOptions(TOptions options, ValidationResult validati } // clusterUri not provided, require both subscription and clusterName - if (string.IsNullOrEmpty(options.ClusterName) || string.IsNullOrEmpty(options.Subscription)) + if (string.IsNullOrEmpty(options.Cluster) || string.IsNullOrEmpty(options.Subscription)) { validationResult.Errors.Add("Either --cluster-uri must be provided, or both --subscription and --cluster must be provided."); } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseDatabaseCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseDatabaseCommand.cs deleted file mode 100644 index f6095eb279..0000000000 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseDatabaseCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics.CodeAnalysis; -using Azure.Mcp.Core.Options; -using Azure.Mcp.Core.Services.Azure.Subscription; -using Azure.Mcp.Tools.Kusto.Options; -using Microsoft.Mcp.Core.Commands; - -namespace Azure.Mcp.Tools.Kusto.Commands; - -public abstract class BaseDatabaseCommand< - [DynamicallyAccessedMembers(TrimAnnotations.CommandAnnotations)] TOptions, TResult>( - ISubscriptionResolver subscriptionResolver) - : BaseClusterCommand(subscriptionResolver) - where TOptions : class, ISubscriptionOption, IDatabaseOption -{ -} diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseTableCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseTableCommand.cs deleted file mode 100644 index 48aef03de4..0000000000 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/BaseTableCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics.CodeAnalysis; -using Azure.Mcp.Core.Options; -using Azure.Mcp.Core.Services.Azure.Subscription; -using Azure.Mcp.Tools.Kusto.Options; -using Microsoft.Mcp.Core.Commands; - -namespace Azure.Mcp.Tools.Kusto.Commands; - -public abstract class BaseTableCommand< - [DynamicallyAccessedMembers(TrimAnnotations.CommandAnnotations)] TOptions, TResult>( - ISubscriptionResolver subscriptionResolver) - : BaseDatabaseCommand(subscriptionResolver) - where TOptions : class, ISubscriptionOption, ITableOption -{ -} diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/ClusterGetCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/ClusterGetCommand.cs index 43a8d10eef..43d6e68292 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/ClusterGetCommand.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/ClusterGetCommand.cs @@ -36,7 +36,7 @@ public override async Task ExecuteAsync(CommandContext context, { var cluster = await kustoService.GetClusterAsync( options.Subscription!, - options.ClusterName, + options.Cluster, options.Tenant, options.RetryPolicy, cancellationToken); @@ -46,7 +46,7 @@ public override async Task ExecuteAsync(CommandContext context, } catch (Exception ex) { - logger.LogError(ex, "An exception occurred getting Kusto cluster details. Cluster: {Cluster}.", options.ClusterName); + logger.LogError(ex, "An exception occurred getting Kusto cluster details. Cluster: {Cluster}.", options.Cluster); HandleException(context, ex); } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/DatabaseListCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/DatabaseListCommand.cs index 97a97e0dde..828af9287f 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/DatabaseListCommand.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/DatabaseListCommand.cs @@ -38,7 +38,6 @@ public override async Task ExecuteAsync(CommandContext context, databasesNames = await kustoService.ListDatabasesAsync( options.ClusterUri!, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -46,9 +45,8 @@ public override async Task ExecuteAsync(CommandContext context, { databasesNames = await kustoService.ListDatabasesAsync( options.Subscription!, - options.ClusterName!, + options.Cluster!, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -57,7 +55,7 @@ public override async Task ExecuteAsync(CommandContext context, } catch (Exception ex) { - logger.LogError(ex, "An exception occurred listing databases. Cluster: {Cluster}.", options.ClusterUri ?? options.ClusterName); + logger.LogError(ex, "An exception occurred listing databases. Cluster: {Cluster}.", options.ClusterUri ?? options.Cluster); HandleException(context, ex); } return context.Response; diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/KustoJsonContext.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/KustoJsonContext.cs index 7a1c90edec..d64000eaba 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/KustoJsonContext.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/KustoJsonContext.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using Azure.Mcp.Tools.Kusto.Services.Models; diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/QueryCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/QueryCommand.cs index 129efe0622..8c69151e05 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/QueryCommand.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/QueryCommand.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Text.Json; using Azure.Mcp.Core.Services.Azure.Subscription; using Azure.Mcp.Tools.Kusto.Options; using Azure.Mcp.Tools.Kusto.Services; @@ -25,7 +26,7 @@ public sealed class QueryCommand( ILogger logger, IKustoService kustoService, ISubscriptionResolver subscriptionResolver) - : BaseDatabaseCommand(subscriptionResolver) + : BaseClusterCommand(subscriptionResolver) { public override async Task ExecuteAsync(CommandContext context, QueryOptions options, CancellationToken cancellationToken) { @@ -40,7 +41,6 @@ public override async Task ExecuteAsync(CommandContext context, options.Database, options.Query, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -48,11 +48,10 @@ public override async Task ExecuteAsync(CommandContext context, { results = await kustoService.QueryItemsAsync( options.Subscription!, - options.ClusterName!, + options.Cluster!, options.Database, options.Query, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -62,7 +61,7 @@ public override async Task ExecuteAsync(CommandContext context, catch (Exception ex) { logger.LogError(ex, "An exception occurred querying Kusto. Cluster: {Cluster}, Database: {Database}," - + " Query: {Query}", options.ClusterUri ?? options.ClusterName, options.Database, options.Query); + + " Query: {Query}", options.ClusterUri ?? options.Cluster, options.Database, options.Query); HandleException(context, ex); } return context.Response; diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/SampleCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/SampleCommand.cs index 2b4a271369..19fe151de7 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/SampleCommand.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/SampleCommand.cs @@ -26,7 +26,7 @@ public sealed class SampleCommand( ILogger logger, IKustoService kustoService, ISubscriptionResolver subscriptionResolver) - : BaseTableCommand(subscriptionResolver) + : BaseClusterCommand(subscriptionResolver) { public override async Task ExecuteAsync(CommandContext context, SampleOptions options, CancellationToken cancellationToken) { @@ -46,7 +46,6 @@ public override async Task ExecuteAsync(CommandContext context, options.Database, query, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -54,11 +53,10 @@ public override async Task ExecuteAsync(CommandContext context, { results = await kustoService.QueryItemsAsync( options.Subscription!, - options.ClusterName!, + options.Cluster!, options.Database, query, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -67,7 +65,7 @@ public override async Task ExecuteAsync(CommandContext context, } catch (Exception ex) { - logger.LogError(ex, "An exception occurred sampling table. Cluster: {Cluster}, Database: {Database}, Table: {Table}.", options.ClusterUri ?? options.ClusterName, options.Database, options.Table); + logger.LogError(ex, "An exception occurred sampling table. Cluster: {Cluster}, Database: {Database}, Table: {Table}.", options.ClusterUri ?? options.Cluster, options.Database, options.Table); HandleException(context, ex); } return context.Response; diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableListCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableListCommand.cs index 44599f3b57..aa9e6b7c05 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableListCommand.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableListCommand.cs @@ -25,7 +25,7 @@ public sealed class TableListCommand( ILogger logger, IKustoService kustoService, ISubscriptionResolver subscriptionResolver) - : BaseDatabaseCommand(subscriptionResolver) + : BaseClusterCommand(subscriptionResolver) { public override async Task ExecuteAsync(CommandContext context, TableListOptions options, CancellationToken cancellationToken) { @@ -39,7 +39,6 @@ public override async Task ExecuteAsync(CommandContext context, options.ClusterUri!, options.Database, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -47,10 +46,9 @@ public override async Task ExecuteAsync(CommandContext context, { tableNames = await kustoService.ListTablesAsync( options.Subscription!, - options.ClusterName!, + options.Cluster!, options.Database, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -59,7 +57,7 @@ public override async Task ExecuteAsync(CommandContext context, } catch (Exception ex) { - logger.LogError(ex, "An exception occurred listing tables. Cluster: {Cluster}, Database: {Database}.", options.ClusterUri ?? options.ClusterName, options.Database); + logger.LogError(ex, "An exception occurred listing tables. Cluster: {Cluster}, Database: {Database}.", options.ClusterUri ?? options.Cluster, options.Database); HandleException(context, ex); } return context.Response; diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableSchemaCommand.cs b/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableSchemaCommand.cs index 5bbaa056cf..f9b163dbe0 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableSchemaCommand.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Commands/TableSchemaCommand.cs @@ -25,7 +25,7 @@ public sealed class TableSchemaCommand( ILogger logger, IKustoService kustoService, ISubscriptionResolver subscriptionResolver) - : BaseTableCommand(subscriptionResolver) + : BaseClusterCommand(subscriptionResolver) { public override async Task ExecuteAsync(CommandContext context, TableSchemaOptions options, CancellationToken cancellationToken) { @@ -40,7 +40,6 @@ public override async Task ExecuteAsync(CommandContext context, options.Database, options.Table, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -48,11 +47,10 @@ public override async Task ExecuteAsync(CommandContext context, { tableSchema = await kustoService.GetTableSchemaAsync( options.Subscription!, - options.ClusterName!, + options.Cluster!, options.Database, options.Table, options.Tenant, - options.AuthMethod, options.RetryPolicy, cancellationToken); } @@ -61,7 +59,7 @@ public override async Task ExecuteAsync(CommandContext context, } catch (Exception ex) { - logger.LogError(ex, "An exception occurred getting table schema. Cluster: {Cluster}, Table: {Table}.", options.ClusterUri ?? options.ClusterName, options.Table); + logger.LogError(ex, "An exception occurred getting table schema. Cluster: {Cluster}, Table: {Table}.", options.ClusterUri ?? options.Cluster, options.Table); HandleException(context, ex); } return context.Response; diff --git a/tools/Azure.Mcp.Tools.Kusto/src/GlobalUsings.cs b/tools/Azure.Mcp.Tools.Kusto/src/GlobalUsings.cs deleted file mode 100644 index 14a017b104..0000000000 --- a/tools/Azure.Mcp.Tools.Kusto/src/GlobalUsings.cs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -global using System.CommandLine; -global using System.Text.Json; diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterGetOptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterGetOptions.cs index 9ef38f7c8a..19f2f3fefc 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterGetOptions.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterGetOptions.cs @@ -2,25 +2,21 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Kusto.Options; -public class ClusterGetOptions : ISubscriptionOption +public sealed class ClusterGetOptions : ISubscriptionOption { - [Option("Kusto Cluster name.", Name = "cluster")] - public required string ClusterName { get; set; } + [Option(Description = KustOptionDescriptions.Cluster)] + public required string Cluster { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.AuthMethod, Name = "auth-method")] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterListOptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterListOptions.cs index 316fe511af..dd01010d49 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterListOptions.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/ClusterListOptions.cs @@ -2,25 +2,21 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Kusto.Options; -public class ClusterListOptions : ISubscriptionOption +public sealed class ClusterListOptions : ISubscriptionOption { - [Option(OptionDescriptions.ResourceGroup, Name = "resource-group")] + [Option(Description = OptionDescriptions.ResourceGroup)] public string? ResourceGroup { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.AuthMethod, Name = "auth-method")] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/DatabaseListOptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/DatabaseListOptions.cs index d9afcd3533..74da8ee1d2 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/DatabaseListOptions.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/DatabaseListOptions.cs @@ -2,28 +2,24 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Kusto.Options; -public class DatabaseListOptions : ISubscriptionOption, IClusterOption +public sealed class DatabaseListOptions : ISubscriptionOption, IClusterOption { - [Option("Kusto Cluster URI.", Name = "cluster-uri")] + [Option(Description = KustOptionDescriptions.ClusterUri)] public string? ClusterUri { get; set; } - [Option("Kusto Cluster name.", Name = "cluster")] - public string? ClusterName { get; set; } + [Option(Description = KustOptionDescriptions.Cluster)] + public string? Cluster { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.AuthMethod, Name = "auth-method")] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/IClusterOption.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/IClusterOption.cs index 9eb5963741..ac36de4643 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/IClusterOption.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/IClusterOption.cs @@ -5,6 +5,6 @@ namespace Azure.Mcp.Tools.Kusto.Options; public interface IClusterOption { - string? ClusterName { get; } + string? Cluster { get; } string? ClusterUri { get; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/KustoOptionDescriptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/KustoOptionDescriptions.cs new file mode 100644 index 0000000000..f6a20f606e --- /dev/null +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/KustoOptionDescriptions.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace Azure.Mcp.Tools.Kusto.Options; + +internal static class KustOptionDescriptions +{ + internal const string ClusterUri = "Kusto Cluster URI."; + internal const string Cluster = "Kusto Cluster name."; + internal const string Database = "Kusto Database name."; + internal const string Table = "Kusto Table name."; +} diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/QueryOptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/QueryOptions.cs index 9830842c56..1b00c31f4b 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/QueryOptions.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/QueryOptions.cs @@ -2,34 +2,30 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Kusto.Options; -public class QueryOptions : ISubscriptionOption, IDatabaseOption +public sealed class QueryOptions : ISubscriptionOption, IDatabaseOption { - [Option("Kusto query to execute. Uses KQL syntax.")] + [Option(Description = "Kusto query to execute. Uses KQL syntax.")] public required string Query { get; set; } - [Option("Kusto Database name.")] + [Option(Description = KustOptionDescriptions.Database)] public required string Database { get; set; } - [Option("Kusto Cluster URI.", Name = "cluster-uri")] + [Option(Description = KustOptionDescriptions.ClusterUri)] public string? ClusterUri { get; set; } - [Option("Kusto Cluster name.", Name = "cluster")] - public string? ClusterName { get; set; } + [Option(Description = KustOptionDescriptions.Cluster)] + public string? Cluster { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.AuthMethod, Name = "auth-method")] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/SampleOptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/SampleOptions.cs index ae13075c0c..987aecb8c9 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/SampleOptions.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/SampleOptions.cs @@ -2,37 +2,33 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Kusto.Options; -public class SampleOptions : ISubscriptionOption, ITableOption +public sealed class SampleOptions : ISubscriptionOption, ITableOption { - [Option("The maximum number of results to return. Must be a positive integer between 1 and 10000. Default is 10.")] + [Option(Description = "The maximum number of results to return. Must be a positive integer between 1 and 10000. Default is 10.")] public int? Limit { get; set; } - [Option("Kusto Table name.")] + [Option(Description = KustOptionDescriptions.Table)] public required string Table { get; set; } - [Option("Kusto Database name.")] + [Option(Description = KustOptionDescriptions.Database)] public required string Database { get; set; } - [Option("Kusto Cluster URI.", Name = "cluster-uri")] + [Option(Description = KustOptionDescriptions.ClusterUri)] public string? ClusterUri { get; set; } - [Option("Kusto Cluster name.", Name = "cluster")] - public string? ClusterName { get; set; } + [Option(Description = KustOptionDescriptions.Cluster)] + public string? Cluster { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.AuthMethod, Name = "auth-method")] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/TableListOptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/TableListOptions.cs index fe8ddb949c..830aa77b29 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/TableListOptions.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/TableListOptions.cs @@ -2,31 +2,27 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Kusto.Options; -public class TableListOptions : ISubscriptionOption, IDatabaseOption +public sealed class TableListOptions : ISubscriptionOption, IDatabaseOption { - [Option("Kusto Database name.")] + [Option(Description = KustOptionDescriptions.Database)] public required string Database { get; set; } - [Option("Kusto Cluster URI.", Name = "cluster-uri")] + [Option(Description = KustOptionDescriptions.ClusterUri)] public string? ClusterUri { get; set; } - [Option("Kusto Cluster name.", Name = "cluster")] - public string? ClusterName { get; set; } + [Option(Description = KustOptionDescriptions.Cluster)] + public string? Cluster { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.AuthMethod, Name = "auth-method")] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Options/TableSchemaOptions.cs b/tools/Azure.Mcp.Tools.Kusto/src/Options/TableSchemaOptions.cs index 80c6290724..fd26f4935c 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Options/TableSchemaOptions.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Options/TableSchemaOptions.cs @@ -2,34 +2,30 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Kusto.Options; -public class TableSchemaOptions : ISubscriptionOption, ITableOption +public sealed class TableSchemaOptions : ISubscriptionOption, ITableOption { - [Option("Kusto Table name.")] + [Option(Description = KustOptionDescriptions.Table)] public required string Table { get; set; } - [Option("Kusto Database name.")] + [Option(Description = KustOptionDescriptions.Database)] public required string Database { get; set; } - [Option("Kusto Cluster URI.", Name = "cluster-uri")] + [Option(Description = KustOptionDescriptions.ClusterUri)] public string? ClusterUri { get; set; } - [Option("Kusto Cluster name.", Name = "cluster")] - public string? ClusterName { get; set; } + [Option(Description = KustOptionDescriptions.Cluster)] + public string? Cluster { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - [Option(OptionDescriptions.AuthMethod, Name = "auth-method")] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Services/IKustoService.cs b/tools/Azure.Mcp.Tools.Kusto/src/Services/IKustoService.cs index b9e6166978..bdda69c34a 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Services/IKustoService.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Services/IKustoService.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Text.Json; using Azure.Mcp.Core.Services.Azure; using Azure.Mcp.Tools.Kusto.Models; using Microsoft.Mcp.Core.Models; @@ -27,7 +28,6 @@ Task GetClusterAsync( Task> ListDatabasesAsync( string clusterUri, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); @@ -35,7 +35,6 @@ Task> ListDatabasesAsync( string subscription, string clusterName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); @@ -44,7 +43,6 @@ Task> QueryItemsAsync( string databaseName, string query, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); @@ -54,7 +52,6 @@ Task> QueryItemsAsync( string databaseName, string query, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); @@ -62,7 +59,6 @@ Task> ListTablesAsync( string clusterUri, string databaseName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); @@ -71,7 +67,6 @@ Task> ListTablesAsync( string clusterName, string databaseName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); @@ -80,7 +75,6 @@ Task GetTableSchemaAsync( string databaseName, string tableName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); @@ -90,7 +84,6 @@ Task GetTableSchemaAsync( string databaseName, string tableName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default); } diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs b/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs index 2571ce606f..6b8fc48a2a 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoClient.cs @@ -263,7 +263,7 @@ private async Task GenerateRequestAsync(string uri, string d return httpRequest; } - private async Task SendRequestAsync(HttpClient httpClient, HttpRequestMessage httpRequest, CancellationToken cancellationToken) + private static async Task SendRequestAsync(HttpClient httpClient, HttpRequestMessage httpRequest, CancellationToken cancellationToken) { var httpResponse = await httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseContentRead, cancellationToken); if (!httpResponse.IsSuccessStatusCode) diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoResult.cs b/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoResult.cs index e50cd8f029..a3cd9259dc 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoResult.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoResult.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Text.Json; + namespace Azure.Mcp.Tools.Kusto.Services; public sealed class KustoResult diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoService.cs b/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoService.cs index a5767e8b1d..9b82690647 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoService.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Services/KustoService.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Text.Json; using Azure.Core; using Azure.Mcp.Core.Services.Azure; using Azure.Mcp.Core.Services.Azure.Subscription; @@ -9,7 +10,6 @@ using Azure.Mcp.Tools.Kusto.Validation; using Microsoft.Extensions.Logging; using Microsoft.Mcp.Core.Helpers; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; using Microsoft.Mcp.Core.Services.Caching; using Microsoft.Mcp.Core.Validation; @@ -116,8 +116,6 @@ public async Task> ListDatabasesAsync( string subscriptionId, string clusterName, string? tenant = null, - AuthMethod? authMethod = - AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { @@ -126,13 +124,12 @@ public async Task> ListDatabasesAsync( (nameof(clusterName), clusterName)); string clusterUri = await GetClusterUriAsync(subscriptionId, clusterName, tenant, retryPolicy); - return await ListDatabasesAsync(clusterUri, tenant, authMethod, retryPolicy, cancellationToken); + return await ListDatabasesAsync(clusterUri, tenant, retryPolicy, cancellationToken); } public async Task> ListDatabasesAsync( string clusterUri, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { @@ -151,7 +148,6 @@ public async Task> ListTablesAsync( string clusterName, string databaseName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { @@ -161,14 +157,13 @@ public async Task> ListTablesAsync( (nameof(databaseName), databaseName)); string clusterUri = await GetClusterUriAsync(subscriptionId, clusterName, tenant, retryPolicy); - return await ListTablesAsync(clusterUri, databaseName, tenant, authMethod, retryPolicy, cancellationToken); + return await ListTablesAsync(clusterUri, databaseName, tenant, retryPolicy, cancellationToken); } public async Task> ListTablesAsync( string clusterUri, string databaseName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { @@ -188,12 +183,11 @@ public async Task GetTableSchemaAsync( string databaseName, string tableName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { string clusterUri = await GetClusterUriAsync(subscriptionId, clusterName, tenant, retryPolicy); - return await GetTableSchemaAsync(clusterUri, databaseName, tableName, tenant, authMethod, retryPolicy, cancellationToken); + return await GetTableSchemaAsync(clusterUri, databaseName, tableName, tenant, retryPolicy, cancellationToken); } public async Task GetTableSchemaAsync( @@ -201,7 +195,6 @@ public async Task GetTableSchemaAsync( string databaseName, string tableName, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { @@ -232,7 +225,6 @@ public async Task> QueryItemsAsync( string databaseName, string query, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { @@ -243,7 +235,7 @@ public async Task> QueryItemsAsync( (nameof(query), query)); string clusterUri = await GetClusterUriAsync(subscriptionId, clusterName, tenant, retryPolicy); - return await QueryItemsAsync(clusterUri, databaseName, query, tenant, authMethod, retryPolicy, cancellationToken); + return await QueryItemsAsync(clusterUri, databaseName, query, tenant, retryPolicy, cancellationToken); } public async Task> QueryItemsAsync( @@ -251,7 +243,6 @@ public async Task> QueryItemsAsync( string databaseName, string query, string? tenant = null, - AuthMethod? authMethod = AuthMethod.Credential, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default) { diff --git a/tools/Azure.Mcp.Tools.Kusto/src/Services/Models/KustoClusterData.cs b/tools/Azure.Mcp.Tools.Kusto/src/Services/Models/KustoClusterData.cs index 64cc81e9a9..4e635b1f1b 100644 --- a/tools/Azure.Mcp.Tools.Kusto/src/Services/Models/KustoClusterData.cs +++ b/tools/Azure.Mcp.Tools.Kusto/src/Services/Models/KustoClusterData.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System.Text.Json; using System.Text.Json.Serialization; using Azure.Mcp.Tools.Kusto.Commands; using Microsoft.Mcp.Core.Services.Azure.Models; diff --git a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterGetCommandTests.cs b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterGetCommandTests.cs index 31a36d95ac..4cc7fd3052 100644 --- a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterGetCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterGetCommandTests.cs @@ -7,7 +7,6 @@ using Azure.Mcp.Tools.Kusto.Models; using Azure.Mcp.Tools.Kusto.Services; using Microsoft.Mcp.Core.Options; -using Microsoft.Mcp.Tests.Client; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; diff --git a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterListCommandTests.cs b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterListCommandTests.cs index 2b7049d396..84fc159f35 100644 --- a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterListCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/ClusterListCommandTests.cs @@ -7,7 +7,6 @@ using Azure.Mcp.Tools.Kusto.Commands; using Azure.Mcp.Tools.Kusto.Services; using Microsoft.Mcp.Core.Options; -using Microsoft.Mcp.Tests.Client; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; diff --git a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/DatabaseListCommandTests.cs b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/DatabaseListCommandTests.cs index 0e72b25796..cef70c52a5 100644 --- a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/DatabaseListCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/DatabaseListCommandTests.cs @@ -5,9 +5,7 @@ using Azure.Mcp.Tests.Commands; using Azure.Mcp.Tools.Kusto.Commands; using Azure.Mcp.Tools.Kusto.Services; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; -using Microsoft.Mcp.Tests.Client; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; @@ -32,13 +30,13 @@ public async Task ExecuteAsync_ReturnsDatabases(string cliArgs, bool useClusterU { Service.ListDatabasesAsync( "https://mycluster.kusto.windows.net", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedDatabases); } else { Service.ListDatabasesAsync( - "sub1", "mycluster", Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + "sub1", "mycluster", Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedDatabases); } @@ -59,13 +57,13 @@ public async Task ExecuteAsync_ReturnsEmpty_WhenNoDatabasesExist(string cliArgs, { Service.ListDatabasesAsync( "https://mycluster.kusto.windows.net", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } else { Service.ListDatabasesAsync( - "sub1", "mycluster", Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + "sub1", "mycluster", Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } @@ -87,13 +85,13 @@ public async Task ExecuteAsync_HandlesException_AndSetsException(string cliArgs, { Service.ListDatabasesAsync( "https://mycluster.kusto.windows.net", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } else { Service.ListDatabasesAsync( - "sub1", "mycluster", Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + "sub1", "mycluster", Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } diff --git a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/QueryCommandTests.cs b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/QueryCommandTests.cs index 2d4fcb25db..cbe2950135 100644 --- a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/QueryCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/QueryCommandTests.cs @@ -6,9 +6,7 @@ using Azure.Mcp.Tests.Commands; using Azure.Mcp.Tools.Kusto.Commands; using Azure.Mcp.Tools.Kusto.Services; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; -using Microsoft.Mcp.Tests.Client; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; @@ -35,14 +33,14 @@ public async Task ExecuteAsync_ReturnsQueryResults(string cliArgs, bool useClust "https://mycluster.kusto.windows.net", "db1", "StormEvents | take 1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedJson); } else { Service.QueryItemsAsync( "sub1", "mycluster", "db1", "StormEvents | take 1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedJson); } @@ -69,14 +67,14 @@ public async Task ExecuteAsync_ReturnsEmpty_WhenNoResults(string cliArgs, bool u "https://mycluster.kusto.windows.net", "db1", "StormEvents | take 1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } else { Service.QueryItemsAsync( "sub1", "mycluster", "db1", "StormEvents | take 1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } @@ -97,14 +95,14 @@ public async Task ExecuteAsync_HandlesException_AndSetsException(string cliArgs, "https://mycluster.kusto.windows.net", "db1", "StormEvents | take 1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } else { Service.QueryItemsAsync( "sub1", "mycluster", "db1", "StormEvents | take 1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } diff --git a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/SampleCommandTests.cs b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/SampleCommandTests.cs index 6721f55e66..83c9ec1915 100644 --- a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/SampleCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/SampleCommandTests.cs @@ -6,9 +6,7 @@ using Azure.Mcp.Tests.Commands; using Azure.Mcp.Tools.Kusto.Commands; using Azure.Mcp.Tools.Kusto.Services; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; -using Microsoft.Mcp.Tests.Client; using NSubstitute; using Xunit; @@ -34,14 +32,14 @@ public async Task ExecuteAsync_ReturnsSampleResults(string cliArgs, bool useClus "https://mycluster.kusto.windows.net", "db1", "['table1'] | sample 10", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedJson); } else { Service.QueryItemsAsync( "sub1", "mycluster", "db1", "['table1'] | sample 10", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedJson); } @@ -68,14 +66,14 @@ public async Task ExecuteAsync_ReturnsEmpty_WhenNoResults(string cliArgs, bool u "https://mycluster.kusto.windows.net", "db1", "['table1'] | sample 10", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } else { Service.QueryItemsAsync( "sub1", "mycluster", "db1", "['table1'] | sample 10", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } @@ -97,14 +95,14 @@ public async Task ExecuteAsync_ReturnsEmpty_WhenNoResults(string cliArgs, bool u // "https://mycluster.kusto.windows.net", // "db1", // "table1 | sample 10", - // Arg.Any(), Arg.Any(), Arg.Any()) + // Arg.Any(), Arg.Any()) // .Returns(Task.FromException>(new Exception("Test error"))); // } // else // { // _kusto.QueryItems( // "sub1", "mycluster", "db1", "table1 | sample 10", - // Arg.Any(), Arg.Any(), Arg.Any()) + // Arg.Any(), Arg.Any()) // .Returns(Task.FromException>(new Exception("Test error"))); // } // var command = new SampleCommand(_logger, _kusto); diff --git a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableListCommandTests.cs b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableListCommandTests.cs index 6317dd3847..b03ecf4f68 100644 --- a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableListCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableListCommandTests.cs @@ -5,9 +5,7 @@ using Azure.Mcp.Tests.Commands; using Azure.Mcp.Tools.Kusto.Commands; using Azure.Mcp.Tools.Kusto.Services; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; -using Microsoft.Mcp.Tests.Client; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; @@ -32,14 +30,14 @@ public async Task ExecuteAsync_ReturnsTables(string cliArgs, bool useClusterUri) Service.ListTablesAsync( "https://mycluster.kusto.windows.net", "db1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedTables); } else { Service.ListTablesAsync( "sub1", "mycluster", "db1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedTables); } @@ -59,14 +57,14 @@ public async Task ExecuteAsync_ReturnsEmpty_WhenNoTables(string cliArgs, bool us Service.ListTablesAsync( "https://mycluster.kusto.windows.net", "db1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } else { Service.ListTablesAsync( "sub1", "mycluster", "db1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns([]); } @@ -86,14 +84,14 @@ public async Task ExecuteAsync_HandlesException_AndSetsException(string cliArgs, Service.ListTablesAsync( "https://mycluster.kusto.windows.net", "db1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } else { Service.ListTablesAsync( "sub1", "mycluster", "db1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } diff --git a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableSchemaCommandTests.cs b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableSchemaCommandTests.cs index 9c4e575d16..1f8a65139f 100644 --- a/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableSchemaCommandTests.cs +++ b/tools/Azure.Mcp.Tools.Kusto/tests/Azure.Mcp.Tools.Kusto.Tests/TableSchemaCommandTests.cs @@ -5,9 +5,7 @@ using Azure.Mcp.Tests.Commands; using Azure.Mcp.Tools.Kusto.Commands; using Azure.Mcp.Tools.Kusto.Services; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; -using Microsoft.Mcp.Tests.Client; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; @@ -34,14 +32,14 @@ public async Task ExecuteAsync_ReturnsSchema(string cliArgs, bool useClusterUri) "https://mycluster.kusto.windows.net", "db1", "table1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedSchema); } else { Service.GetTableSchemaAsync( "sub1", "mycluster", "db1", "table1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .Returns(expectedSchema); } @@ -66,14 +64,14 @@ public async Task ExecuteAsync_ReturnsNull_WhenNoSchema(string cliArgs, bool use "https://mycluster.kusto.windows.net", "db1", "table1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } else { Service.GetTableSchemaAsync( "sub1", "mycluster", "db1", "table1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } @@ -96,14 +94,14 @@ public async Task ExecuteAsync_HandlesException_AndSetsException(string cliArgs, "https://mycluster.kusto.windows.net", "db1", "table1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } else { Service.GetTableSchemaAsync( "sub1", "mycluster", "db1", "table1", - Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) + Arg.Any(), Arg.Any(), Arg.Any()) .ThrowsAsync(new Exception("Test error")); } diff --git a/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountCreateOptions.cs b/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountCreateOptions.cs index 4cb8710d33..961f3cde7e 100644 --- a/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountCreateOptions.cs +++ b/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountCreateOptions.cs @@ -2,41 +2,36 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Storage.Options.Account; public class AccountCreateOptions : ISubscriptionOption { - [Option("The name of the Azure Storage account to create. Must be globally unique, 3-24 characters, lowercase letters and numbers only.")] + [Option(Description = "The name of the Azure Storage account to create. Must be globally unique, 3-24 characters, lowercase letters and numbers only.")] public required string Account { get; set; } - [Option("The Azure region where the storage account will be created (e.g., 'eastus', 'westus2').")] + [Option(Description = "The Azure region where the storage account will be created (e.g., 'eastus', 'westus2').")] public required string Location { get; set; } - [Option("The storage account SKU. Valid values: Standard_LRS, Standard_GRS, Standard_RAGRS, Standard_ZRS, Premium_LRS, Premium_ZRS, Standard_GZRS, Standard_RAGZRS.")] + [Option(Description = "The storage account SKU. Valid values: Standard_LRS, Standard_GRS, Standard_RAGRS, Standard_ZRS, Premium_LRS, Premium_ZRS, Standard_GZRS, Standard_RAGZRS.")] public string? Sku { get; set; } - [Option("The default access tier for blob storage. Valid values: Hot, Cool.")] + [Option(Description = "The default access tier for blob storage. Valid values: Hot, Cool.")] public string? AccessTier { get; set; } - [Option("Whether to enable hierarchical namespace (Data Lake Storage Gen2) for the storage account.")] + [Option(Description = "Whether to enable hierarchical namespace (Data Lake Storage Gen2) for the storage account.")] public bool? EnableHierarchicalNamespace { get; set; } - [Option(OptionDescriptions.ResourceGroup)] + [Option(Description = OptionDescriptions.ResourceGroup)] public required string ResourceGroup { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - // TODO: Remove unused option — registered and visible to the user but never consumed by the command - [Option(OptionDescriptions.AuthMethod)] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountGetOptions.cs b/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountGetOptions.cs index 54029ad2c3..16e316b954 100644 --- a/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountGetOptions.cs +++ b/tools/Azure.Mcp.Tools.Storage/src/Options/Account/AccountGetOptions.cs @@ -2,29 +2,24 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Storage.Options.Account; public class AccountGetOptions : ISubscriptionOption { - [Option("The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] + [Option(Description = "The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] public string? Account { get; set; } - [Option(OptionDescriptions.ResourceGroup)] + [Option(Description = OptionDescriptions.ResourceGroup)] public string? ResourceGroup { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - // TODO: Remove unused option — registered and visible to the user but never consumed by the command - [Option(OptionDescriptions.AuthMethod)] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobGetOptions.cs b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobGetOptions.cs index 25516ff752..503c9c8836 100644 --- a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobGetOptions.cs +++ b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobGetOptions.cs @@ -2,35 +2,30 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Storage.Options.Blob; public class BlobGetOptions : ISubscriptionOption { - [Option("The name of the blob to access within the container. This should be the full path within the container (e.g., 'file.txt' or 'folder/file.txt').")] + [Option(Description = "The name of the blob to access within the container. This should be the full path within the container (e.g., 'file.txt' or 'folder/file.txt').")] public string? Blob { get; set; } - [Option("The prefix to filter blobs when listing blobs in a container. Only blobs whose names start with the specified prefix will be listed.")] + [Option(Description = "The prefix to filter blobs when listing blobs in a container. Only blobs whose names start with the specified prefix will be listed.")] public string? Prefix { get; set; } - [Option("The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] + [Option(Description = "The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] public required string Account { get; set; } - [Option("The name of the container to access within the storage account.")] + [Option(Description = "The name of the container to access within the storage account.")] public required string Container { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - // TODO: Remove unused option — registered and visible to the user but never consumed by the command - [Option(OptionDescriptions.AuthMethod)] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobUploadOptions.cs b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobUploadOptions.cs index a3bc9a31ea..25826c5ca6 100644 --- a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobUploadOptions.cs +++ b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/BlobUploadOptions.cs @@ -2,35 +2,30 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Storage.Options.Blob; public class BlobUploadOptions : ISubscriptionOption { - [Option("The local file path to read content from or to write content to. This should be the full path to the file on your local system.")] + [Option(Description = "The local file path to read content from or to write content to. This should be the full path to the file on your local system.")] public required string LocalFilePath { get; set; } - [Option("The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] + [Option(Description = "The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] public required string Account { get; set; } - [Option("The name of the container to access within the storage account.")] + [Option(Description = "The name of the container to access within the storage account.")] public required string Container { get; set; } - [Option("The name of the blob to access within the container. This should be the full path within the container (e.g., 'file.txt' or 'folder/file.txt').")] + [Option(Description = "The name of the blob to access within the container. This should be the full path within the container (e.g., 'file.txt' or 'folder/file.txt').")] public required string Blob { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - // TODO: Remove unused option — registered and visible to the user but never consumed by the command - [Option(OptionDescriptions.AuthMethod)] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerCreateOptions.cs b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerCreateOptions.cs index 3a01539e2a..12dee5018d 100644 --- a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerCreateOptions.cs +++ b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerCreateOptions.cs @@ -2,29 +2,24 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Storage.Options.Blob.Container; public class ContainerCreateOptions : ISubscriptionOption { - [Option("The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] + [Option(Description = "The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] public required string Account { get; set; } - [Option("The name of the container to access within the storage account.")] + [Option(Description = "The name of the container to access within the storage account.")] public required string Container { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - // TODO: Remove unused option — registered and visible to the user but never consumed by the command - [Option(OptionDescriptions.AuthMethod)] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerGetOptions.cs b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerGetOptions.cs index 0211f35eb7..37a61e533c 100644 --- a/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerGetOptions.cs +++ b/tools/Azure.Mcp.Tools.Storage/src/Options/Blob/Container/ContainerGetOptions.cs @@ -2,32 +2,27 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Storage.Options.Blob.Container; public class ContainerGetOptions : ISubscriptionOption { - [Option("The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] + [Option(Description = "The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] public required string Account { get; set; } - [Option("The name of the container to access within the storage account.")] + [Option(Description = "The name of the container to access within the storage account.")] public string? Container { get; set; } - [Option("The prefix to filter containers when listing containers in a storage account. Only containers whose names start with the specified prefix will be listed.")] + [Option(Description = "The prefix to filter containers when listing containers in a storage account. Only containers whose names start with the specified prefix will be listed.")] public string? Prefix { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - // TODO: Remove unused option — registered and visible to the user but never consumed by the command - [Option(OptionDescriptions.AuthMethod)] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Azure.Mcp.Tools.Storage/src/Options/Table/TableListOptions.cs b/tools/Azure.Mcp.Tools.Storage/src/Options/Table/TableListOptions.cs index 6971ff3830..881559996f 100644 --- a/tools/Azure.Mcp.Tools.Storage/src/Options/Table/TableListOptions.cs +++ b/tools/Azure.Mcp.Tools.Storage/src/Options/Table/TableListOptions.cs @@ -2,26 +2,21 @@ // Licensed under the MIT License. using Azure.Mcp.Core.Options; -using Microsoft.Mcp.Core.Models; using Microsoft.Mcp.Core.Options; namespace Azure.Mcp.Tools.Storage.Options.Table; public class TableListOptions : ISubscriptionOption { - [Option("The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] + [Option(Description = "The name of the Azure Storage account. This is the unique name you chose for your storage account (e.g., 'mystorageaccount').")] public required string Account { get; set; } - [Option(OptionDescriptions.Subscription)] + [Option(Description = OptionDescriptions.Subscription)] public string? Subscription { get; set; } - [Option(OptionDescriptions.Tenant)] + [Option(Description = OptionDescriptions.Tenant)] public string? Tenant { get; set; } - // TODO: Remove unused option — registered and visible to the user but never consumed by the command - [Option(OptionDescriptions.AuthMethod)] - public AuthMethod? AuthMethod { get; set; } - - [Option(Name = "retry")] + [OptionContainer(Prefix = "retry")] public RetryPolicyOptions? RetryPolicy { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.Core/src/Options/ItemCreateOptions.cs b/tools/Fabric.Mcp.Tools.Core/src/Options/ItemCreateOptions.cs index 8d5f1129d0..09b6d69e1b 100644 --- a/tools/Fabric.Mcp.Tools.Core/src/Options/ItemCreateOptions.cs +++ b/tools/Fabric.Mcp.Tools.Core/src/Options/ItemCreateOptions.cs @@ -7,18 +7,18 @@ namespace Fabric.Mcp.Tools.Core.Options; public class ItemCreateOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The display name for the item.")] + [Option(Description = "The display name for the item.")] public required string DisplayName { get; set; } - [Option("The type of the Fabric item (e.g., Lakehouse, Notebook, etc.).")] + [Option(Description = "The type of the Fabric item (e.g., Lakehouse, Notebook, etc.).")] public required string ItemType { get; set; } - [Option("The description for the item.")] + [Option(Description = "The description for the item.")] public string? Description { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/CreateDataflowOptions.cs b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/CreateDataflowOptions.cs index 1ea57e1971..e869472e37 100644 --- a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/CreateDataflowOptions.cs +++ b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/CreateDataflowOptions.cs @@ -7,12 +7,12 @@ namespace Fabric.Mcp.Tools.DataFactory.Options.Dataflow; public class CreateDataflowOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public required string WorkspaceId { get; set; } - [Option("The display name for the item.")] + [Option(Description = "The display name for the item.")] public required string DisplayName { get; set; } - [Option("Optional description for the item.")] + [Option(Description = "Optional description for the item.")] public string? Description { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ExecuteQueryOptions.cs b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ExecuteQueryOptions.cs index 81e6338719..0d1cc3b6b0 100644 --- a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ExecuteQueryOptions.cs +++ b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ExecuteQueryOptions.cs @@ -7,15 +7,15 @@ namespace Fabric.Mcp.Tools.DataFactory.Options.Dataflow; public class ExecuteQueryOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public required string WorkspaceId { get; set; } - [Option("The ID of the dataflow.")] + [Option(Description = "The ID of the dataflow.")] public required string DataflowId { get; set; } - [Option("The name of the query to execute.")] + [Option(Description = "The name of the query to execute.")] public required string QueryName { get; set; } - [Option("The M (Power Query) expression to execute.")] + [Option(Description = "The M (Power Query) expression to execute.")] public required string Query { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ListDataflowsOptions.cs b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ListDataflowsOptions.cs index 373793eccb..28594b3611 100644 --- a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ListDataflowsOptions.cs +++ b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Dataflow/ListDataflowsOptions.cs @@ -7,6 +7,6 @@ namespace Fabric.Mcp.Tools.DataFactory.Options.Dataflow; public class ListDataflowsOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public required string WorkspaceId { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/CreatePipelineOptions.cs b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/CreatePipelineOptions.cs index edfdac3146..a62ba22f40 100644 --- a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/CreatePipelineOptions.cs +++ b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/CreatePipelineOptions.cs @@ -7,12 +7,12 @@ namespace Fabric.Mcp.Tools.DataFactory.Options.Pipeline; public class CreatePipelineOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public required string WorkspaceId { get; set; } - [Option("The display name for the item.")] + [Option(Description = "The display name for the item.")] public required string DisplayName { get; set; } - [Option("Optional description for the item.")] + [Option(Description = "Optional description for the item.")] public string? Description { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/GetPipelineOptions.cs b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/GetPipelineOptions.cs index f1e90b1332..0c124d498a 100644 --- a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/GetPipelineOptions.cs +++ b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/GetPipelineOptions.cs @@ -7,9 +7,9 @@ namespace Fabric.Mcp.Tools.DataFactory.Options.Pipeline; public class GetPipelineOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public required string WorkspaceId { get; set; } - [Option("The ID of the pipeline.")] + [Option(Description = "The ID of the pipeline.")] public required string PipelineId { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/ListPipelinesOptions.cs b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/ListPipelinesOptions.cs index 448e34ebb8..f1a4140e8f 100644 --- a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/ListPipelinesOptions.cs +++ b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/ListPipelinesOptions.cs @@ -7,6 +7,6 @@ namespace Fabric.Mcp.Tools.DataFactory.Options.Pipeline; public class ListPipelinesOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public required string WorkspaceId { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/RunPipelineOptions.cs b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/RunPipelineOptions.cs index 3c7773499c..0b0ee3c188 100644 --- a/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/RunPipelineOptions.cs +++ b/tools/Fabric.Mcp.Tools.DataFactory/src/Options/Pipeline/RunPipelineOptions.cs @@ -7,9 +7,9 @@ namespace Fabric.Mcp.Tools.DataFactory.Options.Pipeline; public class RunPipelineOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public required string WorkspaceId { get; set; } - [Option("The ID of the pipeline.")] + [Option(Description = "The ID of the pipeline.")] public required string PipelineId { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.Docs/src/Options/BestPractices/GetBestPracticesOptions.cs b/tools/Fabric.Mcp.Tools.Docs/src/Options/BestPractices/GetBestPracticesOptions.cs index 4f842d3d86..b2b9df68f9 100644 --- a/tools/Fabric.Mcp.Tools.Docs/src/Options/BestPractices/GetBestPracticesOptions.cs +++ b/tools/Fabric.Mcp.Tools.Docs/src/Options/BestPractices/GetBestPracticesOptions.cs @@ -7,6 +7,6 @@ namespace Fabric.Mcp.Tools.Docs.Options.BestPractices; public class GetBestPracticesOptions { - [Option("The best practice topic to retrieve documentation for.")] + [Option(Description = "The best practice topic to retrieve documentation for.")] public required string Topic { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.Docs/src/Options/PublicApis/WorkloadCommandOptions.cs b/tools/Fabric.Mcp.Tools.Docs/src/Options/PublicApis/WorkloadCommandOptions.cs index 146665bd35..e42932d364 100644 --- a/tools/Fabric.Mcp.Tools.Docs/src/Options/PublicApis/WorkloadCommandOptions.cs +++ b/tools/Fabric.Mcp.Tools.Docs/src/Options/PublicApis/WorkloadCommandOptions.cs @@ -7,6 +7,6 @@ namespace Fabric.Mcp.Tools.Docs.Options.PublicApis; public class WorkloadCommandOptions { - [Option("The type of Microsoft Fabric workload.")] + [Option(Description = "The type of Microsoft Fabric workload.")] public required string WorkloadType { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetBestPracticesCommandTests.cs b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetBestPracticesCommandTests.cs index 738200197c..2847278346 100644 --- a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetBestPracticesCommandTests.cs +++ b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetBestPracticesCommandTests.cs @@ -53,7 +53,7 @@ public async Task GetBestPracticesCommand_ExecuteAsync_WithEmptyTopic_ReturnsBad // Assert Assert.Equal(HttpStatusCode.BadRequest, result.Status); - Assert.Equal("Missing Required options: --topic", result.Message); + Assert.Contains("Missing Required options: --topic", result.Message); Service.DidNotReceive().GetTopicBestPractices(Arg.Any()); } diff --git a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetExamplesCommandTests.cs b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetExamplesCommandTests.cs index 242e03713f..c764a21728 100644 --- a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetExamplesCommandTests.cs +++ b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetExamplesCommandTests.cs @@ -58,7 +58,7 @@ public async Task GetExamplesCommand_ExecuteAsync_WithEmptyWorkloadType_ReturnsB // Assert Assert.Equal(HttpStatusCode.BadRequest, result.Status); - Assert.Equal("Missing Required options: --workload-type", result.Message); + Assert.Contains("Missing Required options: --workload-type", result.Message); await Service.DidNotReceive().GetWorkloadExamplesAsync(Arg.Any(), Arg.Any()); } diff --git a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadApisCommandTests.cs b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadApisCommandTests.cs index abbdfb50b3..6721f5ac58 100644 --- a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadApisCommandTests.cs +++ b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadApisCommandTests.cs @@ -54,7 +54,7 @@ public async Task GetApiSpecCommand_ExecuteAsync_WithEmptyWorkloadType_ReturnsBa // Assert Assert.Equal(HttpStatusCode.BadRequest, result.Status); - Assert.Equal("Missing Required options: --workload-type", result.Message); + Assert.Contains("Missing Required options: --workload-type", result.Message); await Service.DidNotReceive().GetWorkloadPublicApis(Arg.Any(), Arg.Any()); } diff --git a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadDefinitionCommandTests.cs b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadDefinitionCommandTests.cs index 6b4940dc23..94a1873fea 100644 --- a/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadDefinitionCommandTests.cs +++ b/tools/Fabric.Mcp.Tools.Docs/tests/Fabric.Mcp.Tools.Docs.Tests/Commands/GetWorkloadDefinitionCommandTests.cs @@ -53,7 +53,7 @@ public async Task GetItemDefinitionCommand_ExecuteAsync_WithEmptyWorkloadType_Re // Assert Assert.Equal(HttpStatusCode.BadRequest, result.Status); - Assert.Equal("Missing Required options: --workload-type", result.Message); + Assert.Contains("Missing Required options: --workload-type", result.Message); Service.DidNotReceive().GetWorkloadItemDefinition(Arg.Any()); } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobDeleteCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobDeleteCommand.cs index 8d3a8e0c48..cdcbd95ad8 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobDeleteCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobDeleteCommand.cs @@ -92,18 +92,18 @@ public sealed record BlobDeleteCommandResult(BlobDeleteResult Result, string Mes public sealed class BlobDeleteOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the file in OneLake.")] + [Option(Description = "The path to the file in OneLake.")] public required string FilePath { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobGetCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobGetCommand.cs index 53287fc11e..a4d9fbb436 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobGetCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobGetCommand.cs @@ -151,21 +151,21 @@ public sealed record BlobGetCommandResult(BlobGetResult Blob, string Message); public sealed class BlobGetOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the file in OneLake.")] + [Option(Description = "The path to the file in OneLake.")] public required string FilePath { get; set; } - [Option("Local path to save the downloaded content when running locally.")] + [Option(Description = "Local path to save the downloaded content when running locally.")] public string? DownloadFilePath { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobPutCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobPutCommand.cs index aed9c71d08..8405017b73 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobPutCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/BlobPutCommand.cs @@ -149,30 +149,30 @@ public sealed record BlobPutCommandResult( public sealed class BlobPutOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the file in OneLake.")] + [Option(Description = "The path to the file in OneLake.")] public required string FilePath { get; set; } - [Option("The content to write to the file.")] + [Option(Description = "The content to write to the file.")] public string? Content { get; set; } - [Option("The path to a local file to upload.")] + [Option(Description = "The path to a local file to upload.")] public string? LocalFilePath { get; set; } - [Option("Whether to overwrite existing files.")] + [Option(Description = "Whether to overwrite existing files.")] public bool Overwrite { get; set; } - [Option("MIME content type to set on the uploaded file (e.g., 'application/json'). Defaults to 'application/octet-stream'.")] + [Option(Description = "MIME content type to set on the uploaded file (e.g., 'application/json'). Defaults to 'application/octet-stream'.")] public string? ContentType { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryCreateCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryCreateCommand.cs index 82215a2cc7..97f7d40b34 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryCreateCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryCreateCommand.cs @@ -116,18 +116,18 @@ public sealed record DirectoryCreateCommandResult public sealed class DirectoryCreateOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the directory in OneLake.")] + [Option(Description = "The path to the directory in OneLake.")] public required string DirectoryPath { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryDeleteCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryDeleteCommand.cs index 3b96416408..eea31a3a96 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryDeleteCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/DirectoryDeleteCommand.cs @@ -85,21 +85,21 @@ public sealed record DirectoryDeleteCommandResult( public sealed class DirectoryDeleteOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the directory in OneLake.")] + [Option(Description = "The path to the directory in OneLake.")] public required string DirectoryPath { get; set; } - [Option("Whether to perform the operation recursively.")] + [Option(Description = "Whether to perform the operation recursively.")] public bool Recursive { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileDeleteCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileDeleteCommand.cs index f1bf2ed503..0fda824596 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileDeleteCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileDeleteCommand.cs @@ -88,18 +88,18 @@ public sealed record FileDeleteCommandResult( public sealed class FileDeleteOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the file in OneLake.")] + [Option(Description = "The path to the file in OneLake.")] public required string FilePath { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileReadCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileReadCommand.cs index a6e473e809..f55a65972e 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileReadCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileReadCommand.cs @@ -181,21 +181,21 @@ public sealed record FileReadCommandResult( public sealed class FileReadOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the file in OneLake.")] + [Option(Description = "The path to the file in OneLake.")] public required string FilePath { get; set; } - [Option("Local path to save the downloaded content when running locally.")] + [Option(Description = "Local path to save the downloaded content when running locally.")] public string? DownloadFilePath { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileWriteCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileWriteCommand.cs index b9f38422d3..45a32f907f 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileWriteCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/File/FileWriteCommand.cs @@ -124,27 +124,27 @@ public sealed record FileWriteCommandResult( public sealed class FileWriteOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to the file in OneLake.")] + [Option(Description = "The path to the file in OneLake.")] public required string FilePath { get; set; } - [Option("The content to write to the file.")] + [Option(Description = "The content to write to the file.")] public string? Content { get; set; } - [Option("The path to a local file to upload.")] + [Option(Description = "The path to a local file to upload.")] public string? LocalFilePath { get; set; } - [Option("Whether to overwrite existing files.")] + [Option(Description = "Whether to overwrite existing files.")] public bool Overwrite { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemDataListCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemDataListCommand.cs index 56e5b226f1..4a031dac47 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemDataListCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemDataListCommand.cs @@ -94,15 +94,15 @@ public sealed record OneLakeItemDataListCommandResult public sealed class OneLakeItemDataListOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("Whether to perform the operation recursively.")] + [Option(Description = "Whether to perform the operation recursively.")] public bool Recursive { get; set; } - [Option("Token for retrieving the next page of results.")] + [Option(Description = "Token for retrieving the next page of results.")] public string? ContinuationToken { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListCommand.cs index 27528c1b2e..1f7d051206 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListCommand.cs @@ -97,12 +97,12 @@ public OneLakeItemListCommandResult() { } public sealed class OneLakeItemListOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("Token for retrieving the next page of results.")] + [Option(Description = "Token for retrieving the next page of results.")] public string? ContinuationToken { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListDfsCommand.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListDfsCommand.cs index 607727f3dd..3c379f8ac8 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListDfsCommand.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Commands/Item/OneLakeItemListDfsCommand.cs @@ -94,15 +94,15 @@ public sealed record OneLakeItemListDfsCommandResult public sealed class OneLakeItemListDfsOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("Whether to perform the operation recursively.")] + [Option(Description = "Whether to perform the operation recursively.")] public bool Recursive { get; set; } - [Option("Token for retrieving the next page of results.")] + [Option(Description = "Token for retrieving the next page of results.")] public string? ContinuationToken { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/BlobListOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/BlobListOptions.cs index 88584b9f56..488ec337b8 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/BlobListOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/BlobListOptions.cs @@ -7,24 +7,24 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public class BlobListOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to list in OneLake storage (optional, defaults to root).")] + [Option(Description = "The path to list in OneLake storage (optional, defaults to root).")] public string? Path { get; set; } - [Option("Whether to perform the operation recursively.")] + [Option(Description = "Whether to perform the operation recursively.")] public bool Recursive { get; set; } - [Option("Output format for OneLake API responses. Use 'json' for parsed objects, 'xml' for raw XML API response, or 'raw' for unprocessed API response. Supported values: 'json' (default), 'xml', 'raw'.")] + [Option(Description = "Output format for OneLake API responses. Use 'json' for parsed objects, 'xml' for raw XML API response, or 'raw' for unprocessed API response. Supported values: 'json' (default), 'xml', 'raw'.")] public string? Format { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/PathListOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/PathListOptions.cs index b9335e420a..d9cd5404d1 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/PathListOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/PathListOptions.cs @@ -7,24 +7,24 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public class PathListOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The path to list in OneLake storage (optional, defaults to root).")] + [Option(Description = "The path to list in OneLake storage (optional, defaults to root).")] public string? Path { get; set; } - [Option("Whether to perform the operation recursively.")] + [Option(Description = "Whether to perform the operation recursively.")] public bool Recursive { get; set; } - [Option("Output format for OneLake API responses. Use 'json' for parsed objects, 'xml' for raw XML API response, or 'raw' for unprocessed API response. Supported values: 'json' (default), 'xml', 'raw'.")] + [Option(Description = "Output format for OneLake API responses. Use 'json' for parsed objects, 'xml' for raw XML API response, or 'raw' for unprocessed API response. Supported values: 'json' (default), 'xml', 'raw'.")] public string? Format { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableConfigGetOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableConfigGetOptions.cs index 8c73a8bc56..85b4faf2a1 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableConfigGetOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableConfigGetOptions.cs @@ -7,15 +7,15 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public sealed class TableConfigGetOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableGetOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableGetOptions.cs index 7a3b11fae2..c039f3db90 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableGetOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableGetOptions.cs @@ -7,24 +7,24 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public sealed class TableGetOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The table namespace (schema) to inspect within the OneLake table API.")] + [Option(Description = "The table namespace (schema) to inspect within the OneLake table API.")] public string? Namespace { get; set; } - [Option("Alias for --namespace when specifying table schemas in the OneLake table API.")] + [Option(Description = "Alias for --namespace when specifying table schemas in the OneLake table API.")] public string? Schema { get; set; } - [Option("The table name exposed by the OneLake table API.")] + [Option(Description = "The table name exposed by the OneLake table API.")] public required string Table { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableListOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableListOptions.cs index f2dd766d7f..45806e94bd 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableListOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableListOptions.cs @@ -7,21 +7,21 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public sealed class TableListOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The table namespace (schema) to inspect within the OneLake table API.")] + [Option(Description = "The table namespace (schema) to inspect within the OneLake table API.")] public string? Namespace { get; set; } - [Option("Alias for --namespace when specifying table schemas in the OneLake table API.")] + [Option(Description = "Alias for --namespace when specifying table schemas in the OneLake table API.")] public string? Schema { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceGetOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceGetOptions.cs index 029d344ca1..2499084e6f 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceGetOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceGetOptions.cs @@ -7,21 +7,21 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public sealed class TableNamespaceGetOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } - [Option("The table namespace (schema) to inspect within the OneLake table API.")] + [Option(Description = "The table namespace (schema) to inspect within the OneLake table API.")] public string? Namespace { get; set; } - [Option("Alias for --namespace when specifying table schemas in the OneLake table API.")] + [Option(Description = "Alias for --namespace when specifying table schemas in the OneLake table API.")] public string? Schema { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceListOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceListOptions.cs index 104e65b449..e9b7a1bdbc 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceListOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/TableNamespaceListOptions.cs @@ -7,15 +7,15 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public sealed class TableNamespaceListOptions { - [Option("The ID of the Microsoft Fabric workspace.")] + [Option(Description = "The ID of the Microsoft Fabric workspace.")] public string? WorkspaceId { get; set; } - [Option("The name or ID of the Microsoft Fabric workspace.")] + [Option(Description = "The name or ID of the Microsoft Fabric workspace.")] public string? Workspace { get; set; } - [Option("The ID of the Fabric item.")] + [Option(Description = "The ID of the Fabric item.")] public string? ItemId { get; set; } - [Option("The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] + [Option(Description = "The name or ID of the Fabric item. When using friendly names, MUST include the item type suffix (e.g., 'ItemName.Lakehouse', 'ItemName.Warehouse').")] public string? Item { get; set; } } diff --git a/tools/Fabric.Mcp.Tools.OneLake/src/Options/WorkspaceListOptions.cs b/tools/Fabric.Mcp.Tools.OneLake/src/Options/WorkspaceListOptions.cs index 7319599344..512c793f1f 100644 --- a/tools/Fabric.Mcp.Tools.OneLake/src/Options/WorkspaceListOptions.cs +++ b/tools/Fabric.Mcp.Tools.OneLake/src/Options/WorkspaceListOptions.cs @@ -7,9 +7,9 @@ namespace Fabric.Mcp.Tools.OneLake.Options; public sealed class WorkspaceListOptions { - [Option("Token for retrieving the next page of results.")] + [Option(Description = "Token for retrieving the next page of results.")] public string? ContinuationToken { get; set; } - [Option("Output format for OneLake API responses. Use 'json' for parsed objects, 'xml' for raw XML API response, or 'raw' for unprocessed API response. Supported values: 'json' (default), 'xml', 'raw'.")] + [Option(Description = "Output format for OneLake API responses. Use 'json' for parsed objects, 'xml' for raw XML API response, or 'raw' for unprocessed API response. Supported values: 'json' (default), 'xml', 'raw'.")] public string? Format { get; set; } }