Skip to content

Introduce the new options pattern#2637

Open
hallipr wants to merge 7 commits into
mainfrom
users/pahallis/options
Open

Introduce the new options pattern#2637
hallipr wants to merge 7 commits into
mainfrom
users/pahallis/options

Conversation

@hallipr
Copy link
Copy Markdown
Member

@hallipr hallipr commented May 12, 2026

What does this PR do?

This pull request introduces significant refactoring to the Azure MCP command and options infrastructure, primarily to simplify option binding and validation, and to improve consistency across commands. The changes also include updates to retry policy configuration, test adjustments, and new project references.

  • Removed SearchService's ConfigureRetryPolicy in favor of the common base class method

GitHub issue number?

[Link to the GitHub issue this PR addresses]

Pre-merge Checklist

  • Required for All PRs
    • Read contribution guidelines
    • PR title clearly describes the change
    • Commit history is clean with descriptive messages (cleanup guide)
    • Added comprehensive tests for new/modified functionality
    • Created a changelog entry if the change falls among the following: new feature, bug fix, UI/UX update, breaking change, or updated dependencies. Follow the changelog entry guide
  • For MCP tool changes:
    • One tool per PR: This PR adds or modifies only one MCP tool for faster review cycles
    • Updated servers/Azure.Mcp.Server/README.md and/or servers/Fabric.Mcp.Server/README.md documentation
    • Validate README.md changes running the script ./eng/scripts/Process-PackageReadMe.ps1. See Package README
    • For new or modified tool descriptions, ran ToolDescriptionEvaluator and obtained a score of 0.4 or more and a top 3 ranking for all related test prompts
    • For tools with new names, including new tools or renamed tools, update consolidated-tools.json
    • For renamed tools, follow the Tool Rename Checklist and tag the PR with the breaking-change label
    • For new tools associated with Azure services or publicly available tools/APIs/products, add URL to documentation in the PR description
  • Extra steps for Azure MCP Server tool changes:
    • Updated command list in servers/Azure.Mcp.Server/docs/azmcp-commands.md
    • Ran ./eng/scripts/Update-AzCommandsMetadata.ps1 to update tool metadata in azmcp-commands.md (required for CI)
    • Updated test prompts in servers/Azure.Mcp.Server/docs/e2eTestPrompts.md
    • 👉 For Community (non-Microsoft team member) PRs:
      • Security review: Reviewed code for security vulnerabilities, malicious code, or suspicious activities before running tests (crypto mining, spam, data exfiltration, etc.)
      • Manual tests run: added comment /azp run mcp - pullrequest - live to run Live Test Pipeline

Comment thread core/Azure.Mcp.Core/src/Areas/Subscription/Options/SubscriptionListOptions.cs Outdated
Comment thread core/Azure.Mcp.Core/src/Areas/Group/Options/BaseGroupOptions.cs Outdated
@hallipr hallipr force-pushed the users/pahallis/options branch 2 times, most recently from 2b56c66 to 534b462 Compare May 13, 2026 01:05
Comment thread core/Microsoft.Mcp.Core/src/Areas/Server/Commands/ServiceStartCommand.cs Outdated
Comment thread core/Microsoft.Mcp.Core/src/Areas/Server/Commands/ServiceStartCommand.cs Outdated
Comment thread core/Microsoft.Mcp.Core/src/Areas/Server/Options/ServiceStartOptions.cs Outdated
@hallipr hallipr force-pushed the users/pahallis/options branch from 534b462 to d74dad9 Compare May 13, 2026 04:44
Comment thread core/Microsoft.Mcp.Core/src/Commands/CommandFactory.cs Outdated
Comment thread core/Microsoft.Mcp.Core/src/Commands/ValidationResult.cs Outdated
Comment thread core/Microsoft.Mcp.Core/src/Models/Option/OptionInfo.cs Outdated
Comment thread core/Azure.Mcp.Core/src/Services/Azure/Subscription/ISubscriptionResolver.cs Outdated
Comment thread core/Microsoft.Mcp.Core/src/Options/OptionAttribute.cs
Comment thread core/Microsoft.Mcp.Core/src/Options/OptionDescriptor.cs
@hallipr hallipr force-pushed the users/pahallis/options branch from 7b6a3f0 to b64f194 Compare May 14, 2026 07:20
Comment thread core/Azure.Mcp.Core/src/Options/OptionDescriptions.cs
Comment thread core/Azure.Mcp.Core/src/Options/OptionDescriptions.cs
Comment thread core/Azure.Mcp.Core/src/Options/RetryOptionsExtensions.cs
Comment thread core/Azure.Mcp.Core/src/Options/RetryOptionsExtensions.cs Outdated
@hallipr hallipr force-pushed the users/pahallis/options branch from b64f194 to 75de5fc Compare May 14, 2026 19:12
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hallipr
Copy link
Copy Markdown
Member Author

hallipr commented May 14, 2026

/azp run mcp - pullrequest - live

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

hallipr and others added 2 commits May 14, 2026 15:09
Change ResolveSubscription to take a string? subscription parameter instead
of ParseResult, making it easier to mock in unit tests. Update
KeyValueLockSetCommandTests to use NSubstitute mock that returns the input
value, eliminating environment/CLI profile leakage in tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@hallipr hallipr marked this pull request as ready for review May 15, 2026 15:00
Copilot AI review requested due to automatic review settings May 15, 2026 15:00
@hallipr hallipr requested review from joshfree and saikoumudi May 15, 2026 15:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new attribute-driven options binding pattern for MCP commands. Public properties on a typed TOptions POCO are reflected into System.CommandLine Option<T> instances via the new OptionBinder/OptionDescriptor/OptionAttribute/OptionNameConvention pieces, removing the need for hand-written RegisterOptions/BindOptions overrides per command. Alongside this, RetryPolicyOptions is reshaped so all values are nullable (with Has* flags now derived rather than stored), retry configuration is centralized in a ConfigureRetryOptions extension, and a new ISubscriptionResolver abstraction replaces direct calls to CommandHelper in commands that derive from a new SubscriptionCommand<,>/AuthenticatedCommand<,>/BaseCommand<,> hierarchy. The KeyValueLockSetCommand is migrated as the first concrete consumer of the new pattern.

Changes:

  • New options-binding infrastructure (OptionAttribute, OptionDescriptor, OptionBinder, OptionNameConvention, BaseCommand<TOptions,TResult>, AuthenticatedCommand<,>, SubscriptionCommand<,>) and ISubscriptionResolver/SubscriptionResolver.
  • RetryPolicyOptions switched to nullable scalars with derived Has* flags; BaseAzureService.ConfigureRetryPolicy, MonitorService, CosmosService, and SearchService updated; new RetryOptionsExtensions.ConfigureRetryOptions extension added.
  • KeyValueLockSetCommand/KeyValueLockSetOptions migrated to the new pattern; tests/DI updated to register ISubscriptionResolver.
Show a summary per file
File Description
core/Microsoft.Mcp.Core/src/Options/OptionAttribute.cs New attribute declaring CLI option metadata on POCO properties.
core/Microsoft.Mcp.Core/src/Options/OptionDescriptor.cs Reflects POCO properties (with nullability/nesting) into descriptor list.
core/Microsoft.Mcp.Core/src/Options/OptionBinder.cs Registers Option<T> on commands and binds parse results back to instances.
core/Microsoft.Mcp.Core/src/Options/OptionNameConvention.cs Kebab-case conversion for property→option names.
core/Microsoft.Mcp.Core/src/Options/RetryPolicyOptions.cs Switched to nullable scalars; Has* are now derived properties.
core/Microsoft.Mcp.Core/src/Commands/GlobalCommand.cs Updated retry binding to write only when value present.
core/Microsoft.Mcp.Core/src/Commands/BaseCommand`2.cs New typed-options base command with binding/validation pipeline.
core/Microsoft.Mcp.Core/src/Commands/AuthenticatedCommand`2.cs Authenticated typed-options base command with auth-aware error mapping.
core/Microsoft.Mcp.Core/src/Helpers/CommandHelper.cs Adds GetSubscription(string?) overload reused by the resolver.
core/Azure.Mcp.Core/src/Services/Azure/Subscription/ISubscriptionResolver.cs New abstraction over subscription resolution.
core/Azure.Mcp.Core/src/Services/Azure/Subscription/SubscriptionResolver.cs Default implementation delegating to CommandHelper.
core/Azure.Mcp.Core/src/Commands/Subscription/SubscriptionCommand`2.cs Adds subscription option resolution + validation for typed commands.
core/Azure.Mcp.Core/src/Options/ISubscriptionOption.cs Marker interface used by SubscriptionCommand<,>.
core/Azure.Mcp.Core/src/Options/OptionDescriptions.cs Description constants for shared global options.
core/Azure.Mcp.Core/src/Options/RetryOptionsExtensions.cs ConfigureRetryOptions extension on ClientOptions.
core/Azure.Mcp.Core/src/Services/Azure/BaseAzureService.cs Updated to use nullable retry pattern with clamping preserved.
core/Azure.Mcp.Core/tests/.../BaseAzureServiceTests.cs Test data adjusted for nullable RetryPolicyOptions.
core/Azure.Mcp.Core/tests/.../BaseAzureServiceRetryLimitsTests.cs Removed Has* flags from test fixtures.
core/Azure.Mcp.Core/tests/.../RetryPolicyOptionsTests.cs Equality tests updated for nullable semantics.
core/Azure.Mcp.Core/tests/.../CommandFactoryHelpers.cs Registers ISubscriptionResolver substitute in test DI.
servers/Azure.Mcp.Server/src/Program.cs Registers SubscriptionResolver in DI.
tools/Azure.Mcp.Tools.AppConfig/src/AppConfigSetup.cs Adds DI extensions namespace for new registrations.
tools/Azure.Mcp.Tools.AppConfig/src/Commands/KeyValue/Lock/KeyValueLockSetCommand.cs Migrated to SubscriptionCommand<,> and typed-options pipeline.
tools/Azure.Mcp.Tools.AppConfig/src/Options/KeyValue/Lock/KeyValueLockSetOptions.cs Rewritten to use [Option] attributes and nullable retry.
tools/Azure.Mcp.Tools.AppConfig/tests/.../KeyValueLockSetCommandTests.cs Wires ISubscriptionResolver substitute into test services.
tools/Azure.Mcp.Tools.Cosmos/src/Services/CosmosService.cs Uses nullable pattern for retry options.
tools/Azure.Mcp.Tools.Monitor/src/Services/MonitorService.cs Replaces inline retry config with ConfigureRetryOptions.
tools/Azure.Mcp.Tools.Search/src/Services/SearchService.cs Removes obsolete local retry helper.
tools/Azure.Mcp.Tools.Workbooks/tests/.../UpdateWorkbooksCommandTests.cs Updates test assertion for nullable DelaySeconds.

Copilot's findings

  • Files reviewed: 29/29 changed files
  • Comments generated: 3

Comment thread core/Microsoft.Mcp.Core/src/Options/OptionBinder.cs Outdated
Copy link
Copy Markdown
Contributor

@jongio jongio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean refactoring of the options binding infrastructure. The attribute-driven pattern via OptionBinder/OptionDescriptor is a solid replacement for the manual RegisterOptions/BindOptions overrides, and the nullable RetryPolicyOptions simplification removes a lot of boilerplate.

A few things I noticed that existing reviewers haven't covered:

Comment thread tools/Azure.Mcp.Tools.Search/src/Services/SearchService.cs
Comment thread core/Azure.Mcp.Core/src/Options/RetryOptionsExtensions.cs
Comment thread core/Azure.Mcp.Core/src/Options/RetryOptionsExtensions.cs
hallipr and others added 2 commits May 16, 2026 15:00
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

5 participants