diff --git a/.editorconfig b/.editorconfig
index 9c0d816014..e4dea92413 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -15,6 +15,7 @@ indent_size = 4
# C# files
[*.cs]
+file_header_template = Copyright (c) Microsoft Corporation.\nLicensed under the MIT License.
# New line preferences
csharp_new_line_before_open_brace = all # vs-default: any
csharp_new_line_before_else = true # vs-default: true
@@ -33,7 +34,7 @@ csharp_indent_switch_labels = true # vs-default: true
csharp_indent_labels = one_less_than_current # vs-default: one_less_than_current
# Modifier preferences
-csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:error
# avoid this. unless absolutely necessary
dotnet_style_qualification_for_field = false:suggestion # vs-default: false:none
@@ -83,7 +84,7 @@ dotnet_naming_style.camel_case_underscore_style.required_prefix = _
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# Code style defaults
-csharp_using_directive_placement = outside_namespace:suggestion
+csharp_using_directive_placement = outside_namespace:error
dotnet_sort_system_directives_first = true # vs-default: true
csharp_prefer_braces = true:refactoring
csharp_preserve_single_line_blocks = true # vs-default: true
@@ -91,10 +92,13 @@ csharp_preserve_single_line_statements = false # vs-default: true
csharp_prefer_static_local_function = true:suggestion
csharp_prefer_simple_using_statement = false:none
csharp_style_prefer_switch_expression = true:suggestion
+csharp_style_namespace_declarations = file_scoped:error
+csharp_style_namespace_match_folder = true:error
# Code quality
dotnet_style_readonly_field = true:suggestion
-dotnet_code_quality_unused_parameters = non_public:suggestion
+# Safe to warn on all unused parameters as the project is shipped as an application and not a library.
+dotnet_code_quality_unused_parameters = all:error
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion # vs-default: true:suggestion
@@ -167,6 +171,23 @@ dotnet_code_quality.ca1802.api_surface = private, internal
# CA2016: Forward the CancellationToken parameter to methods that take one
dotnet_diagnostic.CA2016.severity = error
+# Diagnostics without corresponding editorconfig options
+# Unused usings
+dotnet_diagnostic.IDE0005.severity = error
+# Invalid string formatting
+dotnet_diagnostic.IDE0043.severity = error
+# Unused/unread private members
+dotnet_diagnostic.IDE0051.severity = error
+dotnet_diagnostic.IDE0052.severity = error
+# Require file header
+dotnet_diagnostic.IDE0073.severity = error
+# Make methods synchronous (remove async modifier from methods without any await statements)
+dotnet_diagnostic.IDE0390.severity = error
+dotnet_diagnostic.IDE0391.severity = error
+
+#
+dotnet_diagnostic.CS1591.severity = none
+
# Xml project files
[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
indent_size = 2
diff --git a/Directory.Build.props b/Directory.Build.props
index 5562f7fc96..7636c6c1a3 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -20,6 +20,8 @@
See: https://learn.microsoft.com/nuget/reference/errors-and-warnings/nu1901-nu1904
-->
$(WarningsNotAsErrors);NU1901;NU1902
+ true
+ true
diff --git a/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureResourceService.cs b/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureResourceService.cs
index ccb78ebe6e..3b874a1769 100644
--- a/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureResourceService.cs
+++ b/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureResourceService.cs
@@ -30,7 +30,7 @@ public abstract class BaseAzureResourceService(
/// Gets the tenant resource for the specified subscription.
///
/// The tenant ID from the subscription
- /// Cancellation token
+ /// The token to monitor for cancellation requests. The default value is .
/// The tenant resource associated with the subscription
private async Task GetTenantResourceAsync(Guid? tenantId, CancellationToken cancellationToken = default)
{
@@ -77,7 +77,7 @@ private async Task ValidateResourceGroupExistsAsync(SubscriptionResource s
/// Optional table name to query (default: "resources")
/// Optional additional KQL filter condition
/// Maximum number of results to return (default: 50)
- /// Cancellation token
+ /// The token to monitor for cancellation requests. The default value is .
/// Optional tenant to use for the query
/// List of resources converted to the specified type
protected async Task> ExecuteResourceQueryAsync(
@@ -157,8 +157,10 @@ protected async Task> ExecuteResourceQueryAsync(
/// The subscription ID or name
/// Optional retry policy configuration
/// Function to convert JsonElement to the target type
+ /// Optional table name to query (default: "resources")
/// Optional additional KQL filter condition
- /// Cancellation token
+ /// Optional tenant to use for the query
+ /// The token to monitor for cancellation requests. The default value is .
/// Single resource converted to the specified type, or null if not found
protected async Task ExecuteSingleResourceQueryAsync(
string resourceType,
@@ -184,6 +186,7 @@ protected async Task> ExecuteResourceQueryAsync(
/// The API version to set for the specified resource type.
/// Optional tenant to use when creating the client.
/// Optional retry policy used by token acquisition.
+ /// The token to monitor for cancellation requests. The default value is .
/// An initialized configured with the requested API version.
protected async Task CreateArmClientWithApiVersionAsync(string resourceTypeForApiVersion, string apiVersion, string? tenant = null, RetryPolicyOptions? retryPolicy = null, CancellationToken cancellationToken = default)
{
@@ -198,7 +201,7 @@ protected async Task CreateArmClientWithApiVersionAsync(string resour
///
/// The ArmClient to use for the call.
/// The resource identifier of the resource to retrieve.
- /// Cancellation token.
+ /// The token to monitor for cancellation requests. The default value is .
/// The instance for the requested resource.
/// Thrown when a required parameter is null.
protected static async Task GetGenericResourceAsync(ArmClient armClient, ResourceIdentifier resourceIdentifier, CancellationToken cancellationToken = default)
@@ -225,6 +228,7 @@ protected static async Task GetGenericResourceAsync(ArmClient a
/// The Azure location for the resource.
/// The content to create or update the resource with.
/// The JSON type information for serialization.
+ /// The token to monitor for cancellation requests. The default value is .
/// The instance for the requested resource.
/// Thrown when a required parameter is null.
/// Thrown when the content is invalid.
diff --git a/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureService.cs b/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureService.cs
index 7687afbf3e..4bc7fed160 100644
--- a/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureService.cs
+++ b/core/Azure.Mcp.Core/src/Services/Azure/BaseAzureService.cs
@@ -7,7 +7,9 @@
using Azure.Core.Pipeline;
using Azure.Mcp.Core.Services.Azure.Tenant;
using Azure.ResourceManager;
+#pragma warning disable IDE0005 // using isn't used in release builds.
using Microsoft.Mcp.Core.Helpers;
+#pragma warning restore IDE0005 // using isn't used in release builds.
using Microsoft.Mcp.Core.Options;
using Microsoft.Mcp.Core.Services.Azure;
@@ -31,7 +33,7 @@ public abstract class BaseAzureService
private static readonly string s_framework;
private static readonly string s_platform;
private static readonly string s_defaultUserAgent;
- private static readonly TimeSpan? s_defaultPollInterval = null;
+ private static TimeSpan? s_defaultPollInterval = null;
static BaseAzureService()
{
@@ -165,13 +167,11 @@ protected static string EscapeKqlString(string value)
protected async Task GetCredential(CancellationToken cancellationToken)
{
- // TODO @vukelich: separate PR for cancellationToken to be required, not optional default
return await GetCredential(null, cancellationToken);
}
protected async Task GetCredential(string? tenant, CancellationToken cancellationToken)
{
- // TODO @vukelich: separate PR for cancellationToken to be required, not optional default
var tenantId = string.IsNullOrEmpty(tenant) ? null : await ResolveTenantIdAsync(tenant, cancellationToken);
try
@@ -188,7 +188,8 @@ protected async Task GetCredential(string? tenant, Cancellation
/// Gets an ARM access token for the given tenant using the ARM default scope.
///
/// Optional tenant ID or name to authenticate against.
- /// Cancellation token.
+ /// The token to monitor for cancellation requests. The default value is .
+ /// An for the ARM default scope.
protected async Task GetArmAccessTokenAsync(string? tenant, CancellationToken cancellationToken)
{
var credential = await GetCredential(tenant, cancellationToken);
@@ -253,6 +254,8 @@ protected static T ConfigureRetryPolicy(T clientOptions, RetryPolicyOptions?
/// Optional Azure tenant ID or name.
/// Optional retry policy configuration.
/// Optional ARM client options.
+ /// The token to monitor for cancellation requests. The default value is .
+ /// An initialized instance.
protected async Task CreateArmClientAsync(
string? tenantIdOrName = null,
RetryPolicyOptions? retryPolicy = null,
@@ -302,7 +305,7 @@ protected static void ValidateRequiredParameters(params (string name, string? va
///
/// The return type.
/// The long-running operation.
- /// The cancellation token that can cancel the request.
+ /// The token to monitor for cancellation requests. The default value is .
/// The response once the long-running operation completes.
protected static async Task WaitForLroCompletionAsync(Operation operation, CancellationToken cancellationToken = default) where T : notnull
{
@@ -322,7 +325,7 @@ protected static async Task WaitForLroCompletionAsync(Operation operation,
/// Waits for the completion of a long-running operation, periodically polling the operation status until it completes.
///
/// The long-running operation.
- /// The cancellation token that can cancel the request.
+ /// The token to monitor for cancellation requests. The default value is .
/// The response once the long-running operation completes.
protected static async Task WaitForLroCompletionAsync(Operation operation, CancellationToken cancellationToken = default)
{
diff --git a/core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs b/core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
index 4d88d6a2ee..86fda3479d 100644
--- a/core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
+++ b/core/Azure.Mcp.Core/src/Services/Azure/Tenant/ITenantService.cs
@@ -20,7 +20,7 @@ public interface ITenantService
///
/// Gets the list of all available Azure tenants.
///
- /// A token to cancel the operation.
+ /// The token to monitor for cancellation requests.
///
/// A task representing the asynchronous operation, with a list of
/// instances.
@@ -31,7 +31,7 @@ public interface ITenantService
/// Gets the tenant ID from either a tenant ID or tenant name.
///
/// The tenant ID or tenant name.
- /// A cancellation token.
+ /// The token to monitor for cancellation requests.
///
/// A task representing the asynchronous operation, with the tenant ID or
/// if not found.
@@ -40,7 +40,7 @@ public interface ITenantService
/// Thrown when a tenant with the specified name is not found.
///
///
- /// Thrown when the tenant has a TenantId.
+ /// Thrown when the tenant has a TenantId.
///
Task GetTenantId(string tenantIdOrName, CancellationToken cancellationToken);
@@ -48,7 +48,7 @@ public interface ITenantService
/// Gets the tenant ID by tenant name.
///
/// The tenant name.
- /// A cancellation token.
+ /// The token to monitor for cancellation requests.
///
/// A task representing the asynchronous operation, with the tenant ID or
/// if not found.
@@ -57,7 +57,7 @@ public interface ITenantService
/// Thrown when a tenant with the specified name is not found.
///
///
- /// Thrown when the tenant has a TenantId.
+ /// Thrown when the tenant has a TenantId.
///
Task GetTenantIdByName(string tenantName, CancellationToken cancellationToken);
@@ -65,7 +65,7 @@ public interface ITenantService
/// Gets the tenant name by tenant ID.
///
/// The tenant ID.
- /// A cancellation token.
+ /// The token to monitor for cancellation requests.
///
/// A task representing the asynchronous operation, with the tenant name or if not found.
///
@@ -73,7 +73,7 @@ public interface ITenantService
/// Thrown when a tenant with the specified ID is not found.
///
///
- /// Thrown when the tenant has a DisplayName.
+ /// Thrown when the tenant has a DisplayName.
///
Task GetTenantNameById(string tenantId, CancellationToken cancellationToken);
@@ -90,7 +90,7 @@ public interface ITenantService
/// Gets an instance of .
///
/// Optional tenant ID. Use in most cases.
- /// A cancellation token.
+ /// The token to monitor for cancellation requests.
///
/// A task representing the asynchronous operation, with a value of .
///
diff --git a/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantService.cs b/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantService.cs
index a50affa3ed..2ef51d5ccb 100644
--- a/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantService.cs
+++ b/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantService.cs
@@ -57,7 +57,7 @@ public async Task> GetTenants(CancellationToken cancellatio
var options = AddDefaultPolicies(new ArmClientOptions());
options.Transport = new HttpClientTransport(GetClient());
options.Environment = CloudConfiguration.ArmEnvironment;
- var client = new ArmClient(await GetCredential(cancellationToken), default, options);
+ var client = new ArmClient(await GetTokenCredentialAsync(null, cancellationToken), default, options);
await foreach (var tenant in client.GetTenants().WithCancellation(cancellationToken))
{
diff --git a/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantServiceCollectionExtensions.cs b/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantServiceCollectionExtensions.cs
index 97679b84ff..a3affa5718 100644
--- a/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantServiceCollectionExtensions.cs
+++ b/core/Azure.Mcp.Core/src/Services/Azure/Tenant/TenantServiceCollectionExtensions.cs
@@ -29,11 +29,12 @@ public static class TenantServiceCollectionExtensions
///
/// -
///
- /// via .
- /// This can be overridden using
- /// based on parsed command line arguments and environment variables.
+ /// via .
///
///
+ /// -
+ /// via .
+ ///
///
///
public static IServiceCollection AddAzureTenantService(this IServiceCollection services)
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/AccessTokenHandlerTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/AccessTokenHandlerTests.cs
index 32911ea42a..9d993856b7 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/AccessTokenHandlerTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/AccessTokenHandlerTests.cs
@@ -4,6 +4,7 @@
using System.Net;
using System.Net.Http.Headers;
using Azure.Core;
+using Microsoft.Mcp.Core;
using Microsoft.Mcp.Core.Services.Azure.Authentication;
using NSubstitute;
using Xunit;
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/CommandFactoryHelpers.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/CommandFactoryHelpers.cs
index 88af56bfa5..d8345449c8 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/CommandFactoryHelpers.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/CommandFactoryHelpers.cs
@@ -53,6 +53,7 @@
using Microsoft.Mcp.Core.Services.Telemetry;
using Microsoft.Mcp.Core.Services.Time;
using NSubstitute;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server;
@@ -106,7 +107,7 @@ public static ICommandFactory CreateCommandFactory(IServiceProvider? serviceProv
var services = serviceProvider ?? CreateDefaultServiceProvider();
var logger = services.GetRequiredService>();
- var configurationOptions = Microsoft.Extensions.Options.Options.Create(new McpServerConfiguration
+ var configurationOptions = ExtensionsOptions.Options.Create(new McpServerConfiguration
{
Name = "Test Server",
ShortName = "test",
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/CommandGroupDiscoveryStrategyTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/CommandGroupDiscoveryStrategyTests.cs
index da340c547e..205e393a59 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/CommandGroupDiscoveryStrategyTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/CommandGroupDiscoveryStrategyTests.cs
@@ -1,11 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using Microsoft.Extensions.Logging;
using Microsoft.Mcp.Core.Areas.Server.Commands.Discovery;
using Microsoft.Mcp.Core.Areas.Server.Options;
using Microsoft.Mcp.Core.Commands;
using Microsoft.Mcp.Tests.Client.Helpers;
+using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands.Discovery;
@@ -17,8 +23,8 @@ private static CommandGroupDiscoveryStrategy CreateStrategy(
string? entryPoint = null)
{
var factory = commandFactory ?? CommandFactoryHelpers.CreateCommandFactory();
- var startOptions = Microsoft.Extensions.Options.Options.Create(options ?? new ServerStartOptions());
- var logger = NSubstitute.Substitute.For>();
+ var startOptions = ExtensionsOptions.Options.Create(options ?? new ServerStartOptions());
+ var logger = Substitute.For>();
var strategy = new CommandGroupDiscoveryStrategy(factory, startOptions, logger);
if (entryPoint != null)
{
@@ -31,8 +37,8 @@ private static CommandGroupDiscoveryStrategy CreateStrategy(
public void Constructor_WithNullCommandFactory_DoesNotThrow()
{
// Arrange
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions());
- var logger = NSubstitute.Substitute.For>();
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions());
+ var logger = Substitute.For>();
// Act & Assert
// Primary constructor syntax doesn't automatically validate null parameters
@@ -45,7 +51,7 @@ public void Constructor_WithNullOptions_DoesNotThrow()
{
// Arrange
var commandFactory = CommandFactoryHelpers.CreateCommandFactory();
- var logger = NSubstitute.Substitute.For>();
+ var logger = Substitute.For>();
// Act & Assert
// Primary constructor syntax doesn't automatically validate null parameters
@@ -58,8 +64,8 @@ public void Constructor_WithValidParameters_InitializesCorrectly()
{
// Arrange
var commandFactory = CommandFactoryHelpers.CreateCommandFactory();
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions());
- var logger = NSubstitute.Substitute.For>();
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions());
+ var logger = Substitute.For>();
// Act
var strategy = new CommandGroupDiscoveryStrategy(commandFactory, options, logger);
@@ -211,7 +217,7 @@ public async Task DiscoverServersAsync_WithNullEntryPoint_UsesCurrentProcessExec
// Assert
Assert.NotEmpty(result);
// When EntryPoint is set to null, CommandGroupServerProvider defaults to current process executable
- var currentProcessPath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName;
+ var currentProcessPath = Process.GetCurrentProcess().MainModule?.FileName;
Assert.All(result, provider =>
{
var actualEntryPoint = ((CommandGroupServerProvider)provider).EntryPoint;
@@ -232,7 +238,7 @@ public async Task DiscoverServersAsync_WithEmptyEntryPoint_ProvidersDefaultToCur
// Assert
Assert.NotEmpty(result);
- var currentProcessPath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName;
+ var currentProcessPath = Process.GetCurrentProcess().MainModule?.FileName;
Assert.All(result, provider =>
{
var actualEntryPoint = ((CommandGroupServerProvider)provider).EntryPoint;
@@ -252,7 +258,7 @@ public async Task DiscoverServersAsync_WithWhitespaceEntryPoint_ProvidersDefault
// Assert
Assert.NotEmpty(result);
- var currentProcessPath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName;
+ var currentProcessPath = Process.GetCurrentProcess().MainModule?.FileName;
Assert.All(result, provider =>
{
var actualEntryPoint = ((CommandGroupServerProvider)provider).EntryPoint;
@@ -446,8 +452,8 @@ public async Task DiscoverServersAsync_ResultCountIsConsistent()
public async Task ShouldDiscoverServers()
{
var commandFactory = CommandFactoryHelpers.CreateCommandFactory();
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions());
- var logger = NSubstitute.Substitute.For>();
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions());
+ var logger = Substitute.For>();
var strategy = new CommandGroupDiscoveryStrategy(commandFactory, options, logger);
var result = await strategy.DiscoverServersAsync(TestContext.Current.CancellationToken);
Assert.NotNull(result);
@@ -457,9 +463,9 @@ public async Task ShouldDiscoverServers()
public async Task ShouldDiscoverServers_ExcludesIgnoredGroupsAndSetsProperties()
{
var commandFactory = CommandFactoryHelpers.CreateCommandFactory();
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions { ReadOnly = true });
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions { ReadOnly = true });
var azmcpEntryPoint = McpTestUtilities.GetAzMcpExecutablePath();
- var logger = NSubstitute.Substitute.For>();
+ var logger = Substitute.For>();
var strategy = new CommandGroupDiscoveryStrategy(commandFactory, options, logger)
{
EntryPoint = azmcpEntryPoint
@@ -490,8 +496,8 @@ public void GetAzmcpExecutablePath_ReturnsCorrectPathForCurrentOS()
Assert.NotEmpty(azmcpPath);
// Should end with the correct executable name for the current OS
- if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(
- System.Runtime.InteropServices.OSPlatform.Windows))
+ if (RuntimeInformation.IsOSPlatform(
+ OSPlatform.Windows))
{
Assert.EndsWith("azmcp.exe", azmcpPath);
}
@@ -502,7 +508,7 @@ public void GetAzmcpExecutablePath_ReturnsCorrectPathForCurrentOS()
}
// Should be in the same directory as the test assembly
- var testAssemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
+ var testAssemblyPath = Assembly.GetExecutingAssembly().Location;
var testDirectory = Path.GetDirectoryName(testAssemblyPath);
var expectedDirectory = Path.GetDirectoryName(azmcpPath);
Assert.Equal(testDirectory, expectedDirectory);
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/ConsolidatedToolDiscoveryStrategyTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/ConsolidatedToolDiscoveryStrategyTests.cs
index 0c97c74898..77a25116c3 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/ConsolidatedToolDiscoveryStrategyTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Discovery/ConsolidatedToolDiscoveryStrategyTests.cs
@@ -9,6 +9,7 @@
using Microsoft.Mcp.Core.Configuration;
using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands.Discovery;
@@ -21,8 +22,8 @@ private static ConsolidatedToolDiscoveryStrategy CreateStrategy(
{
var factory = commandFactory ?? CommandFactoryHelpers.CreateCommandFactory();
var serviceProvider = CommandFactoryHelpers.SetupCommonServices().BuildServiceProvider();
- var startOptions = Microsoft.Extensions.Options.Options.Create(options ?? new ServerStartOptions());
- var configurationOptions = Microsoft.Extensions.Options.Options.Create(new McpServerConfiguration
+ var startOptions = ExtensionsOptions.Options.Create(options ?? new ServerStartOptions());
+ var configurationOptions = ExtensionsOptions.Options.Create(new McpServerConfiguration
{
Name = "Test Server",
ShortName = "test",
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Runtime/McpRuntimeTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Runtime/McpRuntimeTests.cs
index 071b009526..6d456528a4 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Runtime/McpRuntimeTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/Runtime/McpRuntimeTests.cs
@@ -1,12 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+#pragma warning disable MCP9003 // Obsolete RequestContext constructor - migrating during Phase 1
+#pragma warning disable MCP9005 // Deprecated Sampling/Logging APIs - backward compat during Phase 1
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
using Microsoft.Mcp.Core.Areas.Server.Commands.Runtime;
using Microsoft.Mcp.Core.Areas.Server.Commands.ToolLoading;
using Microsoft.Mcp.Core.Areas.Server.Options;
@@ -17,6 +18,7 @@
using ModelContextProtocol.Server;
using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands.Runtime;
@@ -31,8 +33,8 @@ private static ServiceProvider CreateServiceProvider()
return services.BuildServiceProvider();
}
- private static IOptions CreateOptions(ServerStartOptions? options = null) =>
- Microsoft.Extensions.Options.Options.Create(options ?? new ServerStartOptions());
+ private static ExtensionsOptions.IOptions CreateOptions(ServerStartOptions? options = null) =>
+ ExtensionsOptions.Options.Create(options ?? new ServerStartOptions());
private static McpServer CreateMockServer() => Substitute.For();
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsSerializedTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsSerializedTests.cs
index 92279752ff..faebf4aa75 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsSerializedTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsSerializedTests.cs
@@ -3,19 +3,15 @@
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
using Microsoft.Mcp.Core.Areas.Server.Commands;
using Microsoft.Mcp.Core.Areas.Server.Options;
using Microsoft.Mcp.Core.Configuration;
using Microsoft.Mcp.Core.Helpers;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands;
-// This is intentionally placed after the namespace declaration to avoid
-// conflicts with Azure.Mcp.Core.Areas.Server.Options
-using Options = Microsoft.Extensions.Options.Options;
-
public class ServiceCollectionExtensionsSerializedTests
{
private static readonly Assembly s_testAssembly = typeof(ServiceCollectionExtensionsTests).Assembly;
@@ -41,7 +37,7 @@ public void InitializeConfigurationAndOptions_Defaults()
// Assert
var provider = services.BuildServiceProvider();
- var options = provider.GetRequiredService>();
+ var options = provider.GetRequiredService>();
Assert.NotNull(options.Value);
@@ -65,14 +61,14 @@ public void InitializeConfigurationAndOptions_HttpTransport()
{
Transport = TransportTypes.Http,
};
- var services = SetupBaseServices().AddSingleton(Options.Create(serviceStartOptions));
+ var services = SetupBaseServices().AddSingleton(ExtensionsOptions.Options.Create(serviceStartOptions));
// Act
services.InitializeConfigurationAndOptions(s_serverAssembly);
var provider = services.BuildServiceProvider();
// Assert
- var options = provider.GetRequiredService>();
+ var options = provider.GetRequiredService>();
Assert.NotNull(options.Value);
@@ -96,7 +92,7 @@ public void InitializeConfigurationAndOptions_Stdio()
var provider = services.BuildServiceProvider();
// Assert
- var options = provider.GetRequiredService>();
+ var options = provider.GetRequiredService>();
Assert.NotNull(options.Value);
@@ -121,7 +117,7 @@ public void InitializeConfigurationAndOptions_WithSupportLoggingFolder_DisablesT
{
DangerouslyWriteSupportLogsToDir = "/tmp/logs"
};
- var services = SetupBaseServices().AddSingleton(Options.Create(serviceStartOptions));
+ var services = SetupBaseServices().AddSingleton(ExtensionsOptions.Options.Create(serviceStartOptions));
// Act
Environment.SetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY", null);
@@ -129,7 +125,7 @@ public void InitializeConfigurationAndOptions_WithSupportLoggingFolder_DisablesT
var provider = services.BuildServiceProvider();
// Assert
- var options = provider.GetRequiredService>();
+ var options = provider.GetRequiredService>();
Assert.False(options.Value.IsTelemetryEnabled, "Telemetry should be disabled when support logging folder is set");
}
@@ -145,7 +141,7 @@ public void InitializeConfigurationAndOptions_WithSupportLoggingFolderAndEnvVarT
{
DangerouslyWriteSupportLogsToDir = "/tmp/logs"
};
- var services = SetupBaseServices().AddSingleton(Options.Create(serviceStartOptions));
+ var services = SetupBaseServices().AddSingleton(ExtensionsOptions.Options.Create(serviceStartOptions));
// Act
Environment.SetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY", "true");
@@ -153,7 +149,7 @@ public void InitializeConfigurationAndOptions_WithSupportLoggingFolderAndEnvVarT
var provider = services.BuildServiceProvider();
// Assert
- var options = provider.GetRequiredService>();
+ var options = provider.GetRequiredService>();
Assert.False(options.Value.IsTelemetryEnabled, "Telemetry should be disabled when support logging folder is set, regardless of environment variable");
}
@@ -171,7 +167,7 @@ public void InitializeConfigurationAndOptions_WithEmptyOrWhitespaceSupportLoggin
{
DangerouslyWriteSupportLogsToDir = folderPath
};
- var services = SetupBaseServices().AddSingleton(Options.Create(serviceStartOptions));
+ var services = SetupBaseServices().AddSingleton(ExtensionsOptions.Options.Create(serviceStartOptions));
// Act
Environment.SetEnvironmentVariable("AZURE_MCP_COLLECT_TELEMETRY", null);
@@ -179,7 +175,7 @@ public void InitializeConfigurationAndOptions_WithEmptyOrWhitespaceSupportLoggin
var provider = services.BuildServiceProvider();
// Assert
- var options = provider.GetRequiredService>();
+ var options = provider.GetRequiredService>();
Assert.True(options.Value.IsTelemetryEnabled, $"Telemetry should be enabled when support logging folder is '{folderPath}'");
}
}
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsTests.cs
index 4531ec380d..5c1e2dff21 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceCollectionExtensionsTests.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Options;
using Microsoft.Mcp.Core.Areas.Server;
using Microsoft.Mcp.Core.Areas.Server.Commands;
using Microsoft.Mcp.Core.Areas.Server.Commands.Discovery;
@@ -15,12 +14,13 @@
using ModelContextProtocol.Server;
using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands;
public class ServiceCollectionExtensionsTests
{
- private IServiceCollection SetupBaseServices()
+ private static IServiceCollection SetupBaseServices()
{
var services = CommandFactoryHelpers.SetupCommonServices();
services.AddSingleton(sp => CommandFactoryHelpers.CreateCommandFactory(sp));
@@ -37,7 +37,7 @@ private IServiceCollection SetupBaseServices()
Description = "Test description"
};
services.AddSingleton(serverConfiguration);
- services.AddSingleton(Microsoft.Extensions.Options.Options.Create(serverConfiguration));
+ services.AddSingleton(ExtensionsOptions.Options.Create(serverConfiguration));
return services;
}
@@ -191,7 +191,7 @@ public void AddAzureMcpServer_ConfiguresMcpServerOptions()
// Assert
var provider = services.BuildServiceProvider();
- var mcpServerOptions = provider.GetService>()?.Value;
+ var mcpServerOptions = provider.GetService>()?.Value;
// Verify server options are configured
Assert.NotNull(mcpServerOptions);
@@ -219,7 +219,7 @@ public void AddAzureMcpServer_RegistersOptionsWithSameInstance()
// Assert
var provider = services.BuildServiceProvider();
var registeredOptions = provider.GetService();
- var wrappedOptions = provider.GetService>()?.Value;
+ var wrappedOptions = provider.GetService>()?.Value;
// Verify both registrations point to the same instance
Assert.NotNull(registeredOptions);
@@ -251,7 +251,7 @@ public void AddAzureMcpServer_WithReadOnlyOption_RegistersOption()
Assert.True(registeredOptions.ReadOnly);
// Verify the option is also available as IOptions
- var optionsMonitor = provider.GetService>();
+ var optionsMonitor = provider.GetService>();
Assert.NotNull(optionsMonitor);
Assert.True(optionsMonitor.Value.ReadOnly);
}
@@ -399,7 +399,7 @@ public void AddAzureMcpServer_WithNullProvider_ConfiguresNullServerInstructions(
// Assert
var provider = services.BuildServiceProvider();
- var mcpServerOptions = provider.GetService>()?.Value;
+ var mcpServerOptions = provider.GetService>()?.Value;
// Verify server instructions are configured
Assert.NotNull(mcpServerOptions);
@@ -426,7 +426,7 @@ public void AddAzureMcpServer_WithProvider_ConfiguresServerInstructions()
// Assert
var provider = services.BuildServiceProvider();
- var mcpServerOptions = provider.GetService>()?.Value;
+ var mcpServerOptions = provider.GetService>()?.Value;
// Verify server instructions are configured
Assert.NotNull(mcpServerOptions);
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceInfoCommandTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceInfoCommandTests.cs
index 802c5cf335..6758b266ef 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceInfoCommandTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ServiceInfoCommandTests.cs
@@ -6,6 +6,7 @@
using Microsoft.Mcp.Core.Configuration;
using Microsoft.Mcp.Tests.Client;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands;
@@ -24,7 +25,7 @@ public ServiceInfoCommandTests()
Description = "Test Description",
RootCommandGroupName = "azmcp"
};
- Services.AddSingleton(Microsoft.Extensions.Options.Options.Create(_mcpServerConfiguration));
+ Services.AddSingleton(ExtensionsOptions.Options.Create(_mcpServerConfiguration));
}
[Fact]
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/CommandFactoryToolLoaderTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/CommandFactoryToolLoaderTests.cs
index c1e465638c..70514608de 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/CommandFactoryToolLoaderTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/CommandFactoryToolLoaderTests.cs
@@ -4,6 +4,7 @@
using System.CommandLine;
using System.Net;
+using System.Reflection;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@@ -13,8 +14,10 @@
using Microsoft.Mcp.Core.Models.Command;
using Microsoft.Mcp.Core.Options;
using ModelContextProtocol.Protocol;
+using ModelContextProtocol.Server;
using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands.ToolLoading;
@@ -26,16 +29,16 @@ private static (CommandFactoryToolLoader toolLoader, ICommandFactory commandFact
var commandFactory = CommandFactoryHelpers.CreateCommandFactory(serviceProvider);
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var toolLoaderOptions = Microsoft.Extensions.Options.Options.Create(options ?? new ToolLoaderOptions());
+ var toolLoaderOptions = ExtensionsOptions.Options.Create(options ?? new ToolLoaderOptions());
var toolLoader = new CommandFactoryToolLoader(commandFactory, toolLoaderOptions, logger);
return (toolLoader, commandFactory);
}
- private static ModelContextProtocol.Server.RequestContext CreateRequest()
+ private static RequestContext CreateRequest()
{
- var mockServer = Substitute.For();
- return new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsList })
+ var mockServer = Substitute.For();
+ return new RequestContext(mockServer, new() { Method = RequestMethods.ToolsList })
{
Params = new ListToolsRequestParams()
};
@@ -325,8 +328,8 @@ public async Task CallToolHandler_WithValidTool_ExecutesSuccessfully()
var availableCommands = CommandFactory.GetVisibleCommands(commandFactory.AllCommands);
var firstCommand = availableCommands.First();
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -347,8 +350,8 @@ public async Task CallToolHandler_WithNullParams_ReturnsError()
{
var (toolLoader, _) = CreateToolLoader();
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall }, null!);
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall }, null!);
var result = await toolLoader.CallToolHandler(request, TestContext.Current.CancellationToken);
@@ -367,8 +370,8 @@ public async Task CallToolHandler_WithUnknownTool_ReturnsError()
{
var (toolLoader, _) = CreateToolLoader();
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -458,10 +461,10 @@ public async Task CallToolHandler_BeforeListToolsHandler_ExecutesSuccessfully()
var targetCommand = subscriptionListCommand;
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
var arguments = new Dictionary();
- var callToolRequest = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var callToolRequest = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -609,7 +612,7 @@ public async Task ListToolsHandler_EnumOption_IsExportedAsStringType()
var serviceProvider = CommandFactoryHelpers.CreateDefaultServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var toolLoaderOptions = Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions());
+ var toolLoaderOptions = ExtensionsOptions.Options.Create(new ToolLoaderOptions());
var fakeSystemCommand = new Command("fake-enum-get", "A fake command with an enum option for testing.");
OptionBinder.RegisterOptions(fakeSystemCommand);
@@ -620,7 +623,7 @@ public async Task ListToolsHandler_EnumOption_IsExportedAsStringType()
fakeCommand.Metadata.Returns(new ToolMetadata());
var commandFactory = CommandFactoryHelpers.CreateCommandFactory(serviceProvider);
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-enum-get"] = fakeCommand;
@@ -705,7 +708,7 @@ public async Task ListToolsHandler_ToolsWithSecretMetadata_HaveSecretHintInMeta(
var serviceProvider = CommandFactoryHelpers.CreateDefaultServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var toolLoaderOptions = Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions());
+ var toolLoaderOptions = ExtensionsOptions.Options.Create(new ToolLoaderOptions());
// Create a fake command factory that includes a command with secret metadata
var fakeCommand = Substitute.For();
@@ -720,7 +723,7 @@ public async Task ListToolsHandler_ToolsWithSecretMetadata_HaveSecretHintInMeta(
var commandFactory = CommandFactoryHelpers.CreateCommandFactory(serviceProvider);
// Add our fake command to the internal command map using reflection
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-secret-get"] = fakeCommand;
@@ -760,15 +763,15 @@ public async Task CallToolHandler_WithSecretTool_WhenClientDoesNotSupportElicita
.Returns(new CommandResponse { Status = HttpStatusCode.OK, Message = "Secret test response" });
// Add our fake command to the internal command map using reflection
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-secret-get"] = fakeCommand;
// Create mock server without elicitation capabilities
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
mockServer.ClientCapabilities.Returns((ClientCapabilities?)null);
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -800,16 +803,16 @@ public async Task CallToolHandler_WithNonSecretTool_DoesNotTriggerElicitation()
.Returns(new CommandResponse { Status = HttpStatusCode.OK, Message = "Test response" });
// Add our fake command to the internal command map using reflection
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-non-secret-get"] = fakeCommand;
// Create mock server with elicitation capabilities
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
var capabilities = new ClientCapabilities { Elicitation = new ElicitationCapability() };
mockServer.ClientCapabilities.Returns(capabilities);
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -842,15 +845,15 @@ public async Task CallToolHandler_WithSecretTool_WhenDangerouslyDisableElicitati
.Returns(new CommandResponse { Status = HttpStatusCode.OK, Message = "Secret test response" });
// Add our fake command to the internal command map using reflection
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-secret-get"] = fakeCommand;
// Create mock server - elicitation support doesn't matter when bypassed
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
mockServer.ClientCapabilities.Returns((ClientCapabilities?)null);
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -887,15 +890,15 @@ public async Task CallToolHandler_WithSecretTool_WhenDangerouslyDisableElicitati
.Returns(new CommandResponse { Status = HttpStatusCode.OK, Message = "Secret test response" });
// Add our fake command to the internal command map using reflection
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-secret-get"] = fakeCommand;
// Create mock server without elicitation capabilities
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
mockServer.ClientCapabilities.Returns((ClientCapabilities?)null);
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -949,8 +952,8 @@ public async Task CallToolHandler_WithToolFilter_AllowsSpecifiedTool()
var toolOptions = new ToolLoaderOptions { Tool = [specificToolName] };
var (toolLoader, _) = CreateToolLoader(toolOptions);
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -992,8 +995,8 @@ public async Task CallToolHandler_WithToolFilter_RejectsNonSpecifiedTool()
var toolOptions = new ToolLoaderOptions { Tool = [specificToolName] };
var (toolLoader, _) = CreateToolLoader(toolOptions);
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -1031,8 +1034,8 @@ public async Task CallToolHandler_WithToolFilterCaseInsensitive_AllowsSpecifiedT
var toolOptions = new ToolLoaderOptions { Tool = [specificToolName.ToUpperInvariant()] }; // Set filter to uppercase
var (toolLoader, _) = CreateToolLoader(toolOptions);
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -1133,12 +1136,12 @@ public async Task CallToolHandler_WithReadOnlyMode_RejectsNonReadOnlyTool()
fakeCommand.Title.Returns("Fake Write Tool");
fakeCommand.Metadata.Returns(new ToolMetadata { ReadOnly = false });
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-write-tool"] = fakeCommand;
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -1174,12 +1177,12 @@ public async Task CallToolHandler_WithReadOnlyMode_AllowsReadOnlyTool()
fakeCommand.ExecuteAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(new CommandResponse { Status = HttpStatusCode.OK, Message = "Read-only test response" });
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-readonly-tool"] = fakeCommand;
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -1210,12 +1213,12 @@ public async Task CallToolHandler_WithHttpMode_RejectsLocalRequiredTool()
fakeCommand.Title.Returns("Fake Local Tool");
fakeCommand.Metadata.Returns(new ToolMetadata { LocalRequired = true });
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-local-tool"] = fakeCommand;
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -1251,12 +1254,12 @@ public async Task CallToolHandler_WithoutReadOnlyMode_AllowsNonReadOnlyTool()
fakeCommand.ExecuteAsync(Arg.Any(), Arg.Any(), Arg.Any())
.Returns(new CommandResponse { Status = HttpStatusCode.OK, Message = "Write test response" });
- var commandMapField = typeof(CommandFactory).GetField("_commandMap", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ var commandMapField = typeof(CommandFactory).GetField("_commandMap", BindingFlags.NonPublic | BindingFlags.Instance);
var commandMap = (Dictionary)commandMapField!.GetValue(commandFactory)!;
commandMap["fake-write-tool-2"] = fakeCommand;
- var mockServer = Substitute.For();
- var request = new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ var request = new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/NamespaceToolLoaderTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/NamespaceToolLoaderTests.cs
index 2b637a3e8f..a01af8cf42 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/NamespaceToolLoaderTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/NamespaceToolLoaderTests.cs
@@ -1,19 +1,27 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+#pragma warning disable MCP9003 // Obsolete RequestContext constructor - migrating during Phase 1
+#pragma warning disable MCP9005 // Deprecated Sampling/Logging APIs - backward compat during Phase 1
+
+using System.CommandLine;
+using System.Net;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
using Microsoft.Mcp.Core.Areas.Server.Commands.Discovery;
using Microsoft.Mcp.Core.Areas.Server.Commands.ToolLoading;
using Microsoft.Mcp.Core.Areas.Server.Options;
using Microsoft.Mcp.Core.Commands;
using Microsoft.Mcp.Core.Helpers;
+using Microsoft.Mcp.Core.Models.Command;
+using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
+using ModelContextProtocol.Server;
using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands.ToolLoading;
@@ -21,7 +29,7 @@ public sealed class NamespaceToolLoaderTests : IAsyncDisposable
{
private readonly ServiceProvider _serviceProvider;
private readonly ICommandFactory _commandFactory;
- private readonly IOptions _options;
+ private readonly ExtensionsOptions.IOptions _options;
private readonly ILogger _logger;
public NamespaceToolLoaderTests()
@@ -29,7 +37,7 @@ public NamespaceToolLoaderTests()
_serviceProvider = CommandFactoryHelpers.CreateDefaultServiceProvider() as ServiceProvider
?? throw new InvalidOperationException("Failed to create service provider");
_commandFactory = CommandFactoryHelpers.CreateCommandFactory(_serviceProvider);
- _options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions());
+ _options = ExtensionsOptions.Options.Create(new ServerStartOptions());
_logger = NullLogger.Instance;
}
@@ -104,7 +112,7 @@ public async Task ListToolsHandler_CachesResults()
public async Task ListToolsHandler_FiltersNamespacesWhenConfigured()
{
// Arrange
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions
{
Namespace = ["storage", "keyvault"]
});
@@ -138,7 +146,7 @@ public async Task ListToolsHandler_WithReadOnlyOption_ReturnsOnlyReadOnlyTools()
rootGroup.SubGroup.AddRange([storageGroup, keyvaultGroup]);
commandFactory.RootGroup.Returns(rootGroup);
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions
{
ReadOnly = true
});
@@ -171,7 +179,7 @@ public async Task ListToolsHandler_WithIsHttpOption_DoesNotReturnLocalRequiredTo
rootGroup.SubGroup.AddRange([stroageGroup, keyvaultGroup]);
commandFactory.RootGroup.Returns(rootGroup);
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions
{
Transport = TransportTypes.Http
});
@@ -530,7 +538,7 @@ public void CreateClientOptions_WithElicitationCapability_ReturnsOptionsWithElic
{
// Arrange
var loader = new NamespaceToolLoader(_commandFactory, _options, _logger);
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
var capabilities = new ClientCapabilities
{
Elicitation = new ElicitationCapability()
@@ -551,7 +559,7 @@ public void CreateClientOptions_WithNoElicitationCapability_ReturnsOptionsWithou
{
// Arrange
var loader = new NamespaceToolLoader(_commandFactory, _options, _logger);
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
mockServer.ClientCapabilities.Returns(new ClientCapabilities());
// Act
@@ -568,7 +576,7 @@ public async Task CreateClientOptions_ElicitationHandler_DelegatesToServerSendRe
{
// Arrange
var loader = new NamespaceToolLoader(_commandFactory, _options, _logger);
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
var capabilities = new ClientCapabilities
{
Elicitation = new ElicitationCapability()
@@ -621,7 +629,7 @@ public async Task CreateClientOptions_ElicitationHandler_ValidatesRequestAndThro
{
// Arrange
var loader = new NamespaceToolLoader(_commandFactory, _options, _logger);
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
var capabilities = new ClientCapabilities
{
Elicitation = new ElicitationCapability()
@@ -648,11 +656,11 @@ public async Task CallToolHandler_ReadOnlyMode_RejectsNonReadOnlyCommand()
var executed = false;
var writeCmd = Substitute.For();
writeCmd.Metadata.Returns(new ToolMetadata { ReadOnly = false });
- writeCmd.GetCommand().Returns(new System.CommandLine.Command("write-cmd", "A write command"));
+ writeCmd.GetCommand().Returns(new Command("write-cmd", "A write command"));
writeCmd.ExecuteAsync(default!, default!, default!).ReturnsForAnyArgs(call =>
{
executed = true;
- return new Microsoft.Mcp.Core.Models.Command.CommandResponse { Status = System.Net.HttpStatusCode.OK };
+ return new CommandResponse { Status = HttpStatusCode.OK };
});
storageGroup.AddCommand("write-cmd", writeCmd);
@@ -661,7 +669,7 @@ public async Task CallToolHandler_ReadOnlyMode_RejectsNonReadOnlyCommand()
commandFactory.GroupCommands(Arg.Any())
.Returns(new Dictionary { ["write-cmd"] = writeCmd });
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions { ReadOnly = true });
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions { ReadOnly = true });
var loader = new NamespaceToolLoader(commandFactory, options, _logger);
var request = CreateCallToolRequest("storage", new Dictionary
@@ -688,11 +696,11 @@ public async Task CallToolHandler_ReadOnlyMode_AllowsReadOnlyCommand()
var executed = false;
var readCmd = Substitute.For();
readCmd.Metadata.Returns(new ToolMetadata { ReadOnly = true, Destructive = false });
- readCmd.GetCommand().Returns(new System.CommandLine.Command("read-cmd", "A read command"));
+ readCmd.GetCommand().Returns(new Command("read-cmd", "A read command"));
readCmd.ExecuteAsync(default!, default!, default!).ReturnsForAnyArgs(call =>
{
executed = true;
- return new Microsoft.Mcp.Core.Models.Command.CommandResponse { Status = System.Net.HttpStatusCode.OK };
+ return new CommandResponse { Status = HttpStatusCode.OK };
});
storageGroup.AddCommand("read-cmd", readCmd);
@@ -701,7 +709,7 @@ public async Task CallToolHandler_ReadOnlyMode_AllowsReadOnlyCommand()
commandFactory.GroupCommands(Arg.Any())
.Returns(new Dictionary { ["read-cmd"] = readCmd });
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions { ReadOnly = true });
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions { ReadOnly = true });
var loader = new NamespaceToolLoader(commandFactory, options, _logger);
var request = CreateCallToolRequest("storage", new Dictionary
@@ -728,11 +736,11 @@ public async Task CallToolHandler_HttpMode_RejectsLocalRequiredCommand()
var executed = false;
var localCmd = Substitute.For();
localCmd.Metadata.Returns(new ToolMetadata { LocalRequired = true });
- localCmd.GetCommand().Returns(new System.CommandLine.Command("local-cmd", "A local command"));
+ localCmd.GetCommand().Returns(new Command("local-cmd", "A local command"));
localCmd.ExecuteAsync(default!, default!, default!).ReturnsForAnyArgs(call =>
{
executed = true;
- return new Microsoft.Mcp.Core.Models.Command.CommandResponse { Status = System.Net.HttpStatusCode.OK };
+ return new CommandResponse { Status = HttpStatusCode.OK };
});
storageGroup.AddCommand("local-cmd", localCmd);
@@ -741,7 +749,7 @@ public async Task CallToolHandler_HttpMode_RejectsLocalRequiredCommand()
commandFactory.GroupCommands(Arg.Any())
.Returns(new Dictionary { ["local-cmd"] = localCmd });
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions { Transport = TransportTypes.Http });
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions { Transport = TransportTypes.Http });
var loader = new NamespaceToolLoader(commandFactory, options, _logger);
var request = CreateCallToolRequest("storage", new Dictionary
@@ -768,11 +776,11 @@ public async Task CallToolHandler_HttpMode_AllowsNonLocalRequiredCommand()
var executed = false;
var remoteCmd = Substitute.For();
remoteCmd.Metadata.Returns(new ToolMetadata { LocalRequired = false, Destructive = false });
- remoteCmd.GetCommand().Returns(new System.CommandLine.Command("remote-cmd", "A remote command"));
+ remoteCmd.GetCommand().Returns(new Command("remote-cmd", "A remote command"));
remoteCmd.ExecuteAsync(default!, default!, default!).ReturnsForAnyArgs(call =>
{
executed = true;
- return new Microsoft.Mcp.Core.Models.Command.CommandResponse { Status = System.Net.HttpStatusCode.OK };
+ return new CommandResponse { Status = HttpStatusCode.OK };
});
storageGroup.AddCommand("remote-cmd", remoteCmd);
@@ -781,7 +789,7 @@ public async Task CallToolHandler_HttpMode_AllowsNonLocalRequiredCommand()
commandFactory.GroupCommands(Arg.Any())
.Returns(new Dictionary { ["remote-cmd"] = remoteCmd });
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions { Transport = TransportTypes.Http });
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions { Transport = TransportTypes.Http });
var loader = new NamespaceToolLoader(commandFactory, options, _logger);
var request = CreateCallToolRequest("storage", new Dictionary
@@ -798,10 +806,10 @@ public async Task CallToolHandler_HttpMode_AllowsNonLocalRequiredCommand()
}
[Fact]
- public async Task GetChildToolList_WithReadOnlyOption_ReturnsOnlyReadOnlyTools()
+ public void GetChildToolList_WithReadOnlyOption_ReturnsOnlyReadOnlyTools()
{
// Arrange
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions
{
ReadOnly = true
});
@@ -818,10 +826,10 @@ public async Task GetChildToolList_WithReadOnlyOption_ReturnsOnlyReadOnlyTools()
}
[Fact]
- public async Task GetChildToolList_WithIsHttpOption_DoesNotReturnLocalRequiredTools()
+ public void GetChildToolList_WithIsHttpOption_DoesNotReturnLocalRequiredTools()
{
// Arrange
- var options = Microsoft.Extensions.Options.Options.Create(new ServerStartOptions
+ var options = ExtensionsOptions.Options.Create(new ServerStartOptions
{
Transport = TransportTypes.Http
});
@@ -853,13 +861,13 @@ private string GetFirstAvailableNamespace()
return namespaces.FirstOrDefault() ?? "storage";
}
- private static ModelContextProtocol.Server.RequestContext CreateListToolsRequest()
+ private static RequestContext CreateListToolsRequest()
{
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
return new(mockServer, new() { Method = RequestMethods.ToolsList }, new ListToolsRequestParams());
}
- private static ModelContextProtocol.Server.RequestContext CreateCallToolRequest(
+ private static RequestContext CreateCallToolRequest(
string toolName,
Dictionary arguments)
{
@@ -867,7 +875,7 @@ private static ModelContextProtocol.Server.RequestContext
kvp => kvp.Key,
kvp => JsonSerializer.SerializeToElement(kvp.Value));
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
return new(mockServer, new() { Method = RequestMethods.ToolsCall }, new CallToolRequestParams
{
Name = toolName,
@@ -875,11 +883,11 @@ private static ModelContextProtocol.Server.RequestContext
});
}
- private static ModelContextProtocol.Server.RequestContext CreateCallToolRequestWithJsonElements(
+ private static RequestContext CreateCallToolRequestWithJsonElements(
string toolName,
Dictionary arguments)
{
- var mockServer = Substitute.For();
+ var mockServer = Substitute.For();
return new(mockServer, new() { Method = RequestMethods.ToolsCall }, new CallToolRequestParams
{
Name = toolName,
@@ -887,9 +895,9 @@ private static ModelContextProtocol.Server.RequestContext
});
}
- private static ModelContextProtocol.Client.McpClientOptions CallCreateClientOptions(
+ private static McpClientOptions CallCreateClientOptions(
NamespaceToolLoader loader,
- ModelContextProtocol.Server.McpServer server)
+ McpServer server)
{
// Use reflection to call the protected CreateClientOptions method
var method = typeof(BaseToolLoader).GetMethod(
@@ -902,7 +910,7 @@ private static ModelContextProtocol.Client.McpClientOptions CallCreateClientOpti
}
var result = method.Invoke(loader, [server]);
- return (ModelContextProtocol.Client.McpClientOptions)result!;
+ return (McpClientOptions)result!;
}
public async ValueTask DisposeAsync()
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/PluginTelemetryCommandTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/PluginTelemetryCommandTests.cs
index 190d37cdc7..3fb111749d 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/PluginTelemetryCommandTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/PluginTelemetryCommandTests.cs
@@ -15,6 +15,7 @@
using Microsoft.Mcp.Core.Services.Telemetry;
using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands.ToolLoading;
@@ -42,7 +43,7 @@ public PluginTelemetryCommandTests()
// Build a real CommandFactory with ServerSetup to get actual registered commands
var services = new ServiceCollection();
services.AddSingleton(new ServerSetup());
- services.AddSingleton(Microsoft.Extensions.Options.Options.Create(new McpServerConfiguration
+ services.AddSingleton(ExtensionsOptions.Options.Create(new McpServerConfiguration
{
RootCommandGroupName = "azmcp",
Name = "Azure.Mcp.Server.Test",
diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/RegistryToolLoaderTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/RegistryToolLoaderTests.cs
index 9a5ff261a8..f0d2f7ef2d 100644
--- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/RegistryToolLoaderTests.cs
+++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.Tests/Areas/Server/Commands/ToolLoading/RegistryToolLoaderTests.cs
@@ -12,8 +12,10 @@
using Microsoft.Mcp.Core.Helpers;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
+using ModelContextProtocol.Server;
using NSubstitute;
using Xunit;
+using ExtensionsOptions = Microsoft.Extensions.Options;
namespace Azure.Mcp.Core.Tests.Areas.Server.Commands.ToolLoading;
@@ -25,25 +27,25 @@ private static (RegistryToolLoader toolLoader, IMcpDiscoveryStrategy mockDiscove
var loggerFactory = serviceProvider.GetRequiredService();
var mockDiscoveryStrategy = new MockMcpDiscoveryStrategyBuilder().Build();
var logger = loggerFactory.CreateLogger();
- var toolLoaderOptions = Microsoft.Extensions.Options.Options.Create(options ?? new ToolLoaderOptions());
+ var toolLoaderOptions = ExtensionsOptions.Options.Create(options ?? new ToolLoaderOptions());
var toolLoader = new RegistryToolLoader(mockDiscoveryStrategy, toolLoaderOptions, logger);
return (toolLoader, mockDiscoveryStrategy);
}
- private static ModelContextProtocol.Server.RequestContext CreateListToolsRequest()
+ private static RequestContext CreateListToolsRequest()
{
- var mockServer = Substitute.For();
- return new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsList })
+ var mockServer = Substitute.For();
+ return new RequestContext(mockServer, new() { Method = RequestMethods.ToolsList })
{
Params = new ListToolsRequestParams()
};
}
- private static ModelContextProtocol.Server.RequestContext CreateCallToolRequest(string toolName, IDictionary? arguments = null)
+ private static RequestContext CreateCallToolRequest(string toolName, IDictionary? arguments = null)
{
- var mockServer = Substitute.For();
- return new ModelContextProtocol.Server.RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
+ var mockServer = Substitute.For();
+ return new RequestContext(mockServer, new() { Method = RequestMethods.ToolsCall })
{
Params = new CallToolRequestParams
{
@@ -87,7 +89,7 @@ public async Task ListToolsHandler_WithMockServerProvider_ReturnsExpectedStructu
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions());
+ var serviceOptions = ExtensionsOptions.Options.Create(new ToolLoaderOptions());
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -135,7 +137,7 @@ public async Task ListToolsHandler_WithReadOnlyOption_FiltersProperly()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(readOnlyOptions);
+ var serviceOptions = ExtensionsOptions.Options.Create(readOnlyOptions);
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -151,7 +153,7 @@ public async Task ListToolsHandler_WithReadOnlyOption_FiltersProperly()
Assert.Single(result.Tools);
var returnedTool = result.Tools.First();
Assert.Equal("readonly-tool", returnedTool.Name);
- Assert.True(returnedTool.Annotations?.ReadOnlyHint == true, "Returned tool should have ReadOnlyHint = true");
+ Assert.True(returnedTool.Annotations?.ReadOnlyHint, "Returned tool should have ReadOnlyHint = true");
// Verify that the write tool was filtered out
Assert.DoesNotContain(result.Tools, t => t.Name == "write-tool");
@@ -189,7 +191,7 @@ public async Task ListToolsHandler_WithReadOnlyDisabled_ReturnsAllTools()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(defaultOptions);
+ var serviceOptions = ExtensionsOptions.Options.Create(defaultOptions);
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -209,8 +211,8 @@ public async Task ListToolsHandler_WithReadOnlyDisabled_ReturnsAllTools()
// Verify annotations are preserved
var readOnlyToolResult = result.Tools.First(t => t.Name == "readonly-tool");
var writeToolResult = result.Tools.First(t => t.Name == "write-tool");
- Assert.True(readOnlyToolResult.Annotations?.ReadOnlyHint == true);
- Assert.True(writeToolResult.Annotations?.ReadOnlyHint == false);
+ Assert.True(readOnlyToolResult.Annotations?.ReadOnlyHint);
+ Assert.False(writeToolResult.Annotations?.ReadOnlyHint);
}
[Fact]
@@ -248,7 +250,7 @@ public async Task ListToolsHandler_WithIsHttpOption_FiltersProperly()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(isHttpOptions);
+ var serviceOptions = ExtensionsOptions.Options.Create(isHttpOptions);
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -306,7 +308,7 @@ public async Task ListToolsHandler_WithIsHttpDisabled_ReturnsAllTools()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(isHttpOptions);
+ var serviceOptions = ExtensionsOptions.Options.Create(isHttpOptions);
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -373,9 +375,9 @@ public async Task RegistryToolLoader_WithDifferentOptions_BehavesConsistently()
var logger2 = loggerFactory.CreateLogger();
var defaultToolLoader = new RegistryToolLoader(defaultDiscoveryStrategy,
- Microsoft.Extensions.Options.Options.Create(defaultOptions), logger1);
+ ExtensionsOptions.Options.Create(defaultOptions), logger1);
var readOnlyToolLoader = new RegistryToolLoader(readOnlyDiscoveryStrategy,
- Microsoft.Extensions.Options.Options.Create(readOnlyOptions), logger2);
+ ExtensionsOptions.Options.Create(readOnlyOptions), logger2);
var request = CreateListToolsRequest();
@@ -415,7 +417,7 @@ public async Task CallToolHandler_WithoutListToolsFirst_ShouldSucceed()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions());
+ var serviceOptions = ExtensionsOptions.Options.Create(new ToolLoaderOptions());
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
var request = CreateCallToolRequest("microsoft_docs_search",
@@ -470,7 +472,7 @@ public async Task MockMcpClient_WithExtensionMethods_WorksCorrectly()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions());
+ var serviceOptions = ExtensionsOptions.Options.Create(new ToolLoaderOptions());
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
@@ -542,7 +544,7 @@ public async Task ListToolsHandler_WithReadOnlyOption_FilterToolsWithNullAnnotat
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(readOnlyOptions);
+ var serviceOptions = ExtensionsOptions.Options.Create(readOnlyOptions);
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -559,7 +561,7 @@ public async Task ListToolsHandler_WithReadOnlyOption_FilterToolsWithNullAnnotat
Assert.Single(result.Tools);
var returnedTool = result.Tools.First();
Assert.Equal("readonly-tool", returnedTool.Name);
- Assert.True(returnedTool.Annotations?.ReadOnlyHint == true);
+ Assert.True(returnedTool.Annotations?.ReadOnlyHint);
// Verify that the tool without annotations was filtered out
Assert.DoesNotContain(result.Tools, t => t.Name == "tool-no-annotations");
@@ -684,7 +686,7 @@ public async Task ListToolsHandler_WithMultipleServers_InitializesConcurrently()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions());
+ var serviceOptions = ExtensionsOptions.Options.Create(new ToolLoaderOptions());
var toolLoader = new RegistryToolLoader(mockDiscoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -757,7 +759,7 @@ public async Task ListToolsHandler_WhenCancellationOccursDuringInitialization_Al
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions());
+ var serviceOptions = ExtensionsOptions.Options.Create(new ToolLoaderOptions());
var toolLoader = new RegistryToolLoader(mockDiscoveryStrategy, serviceOptions, logger);
var request = CreateListToolsRequest();
@@ -793,7 +795,7 @@ public async Task ListToolsHandler_WithToolPrefix_ExposesToolsWithPrefix()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var logger = serviceProvider.GetRequiredService().CreateLogger();
- var toolLoader = new RegistryToolLoader(discoveryStrategy, Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions()), logger);
+ var toolLoader = new RegistryToolLoader(discoveryStrategy, ExtensionsOptions.Options.Create(new ToolLoaderOptions()), logger);
// Act
var result = await toolLoader.ListToolsHandler(CreateListToolsRequest(), TestContext.Current.CancellationToken);
@@ -828,7 +830,7 @@ public async Task CallToolHandler_WithToolPrefix_RoutesUsingOriginalName()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var logger = serviceProvider.GetRequiredService().CreateLogger();
- var toolLoader = new RegistryToolLoader(discoveryStrategy, Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions()), logger);
+ var toolLoader = new RegistryToolLoader(discoveryStrategy, ExtensionsOptions.Options.Create(new ToolLoaderOptions()), logger);
// Act — call using the prefixed name
var result = await toolLoader.CallToolHandler(
@@ -856,7 +858,7 @@ public async Task ListToolsHandler_WithNoToolPrefix_ExposesToolsUnchanged()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var logger = serviceProvider.GetRequiredService().CreateLogger();
- var toolLoader = new RegistryToolLoader(discoveryStrategy, Microsoft.Extensions.Options.Options.Create(new ToolLoaderOptions()), logger);
+ var toolLoader = new RegistryToolLoader(discoveryStrategy, ExtensionsOptions.Options.Create(new ToolLoaderOptions()), logger);
// Act
var result = await toolLoader.ListToolsHandler(CreateListToolsRequest(), TestContext.Current.CancellationToken);
@@ -898,7 +900,7 @@ public async Task CallToolHandler_WithReadOnlyMode_RejectsNonReadOnlyTool()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService();
var logger = loggerFactory.CreateLogger();
- var serviceOptions = Microsoft.Extensions.Options.Options.Create(readOnlyOptions);
+ var serviceOptions = ExtensionsOptions.Options.Create(readOnlyOptions);
var toolLoader = new RegistryToolLoader(discoveryStrategy, serviceOptions, logger);
@@ -946,7 +948,7 @@ public async Task CallToolHandler_WithReadOnlyMode_AllowsReadOnlyTool()
var serviceProvider = new ServiceCollection().AddLogging().BuildServiceProvider();
var loggerFactory = serviceProvider.GetRequiredService