From ed9795a95ff7d154cde7c9413bcc8acbe8b73b1d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Sep 2025 17:52:11 +0000 Subject: [PATCH 1/2] Initial plan From da5846e94cdc72039ed3f0c91431ed310e8f0a57 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Sep 2025 17:59:16 +0000 Subject: [PATCH 2/2] Implement IOptionsFormatter on McpOptions Co-authored-by: mathewc <1056548+mathewc@users.noreply.github.com> --- .../Configuration/McpOptions.cs | 22 +++++++++- test/Extensions.Mcp.Tests/McpOptionsTests.cs | 43 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Azure.Functions.Extensions.Mcp/Configuration/McpOptions.cs b/src/Microsoft.Azure.Functions.Extensions.Mcp/Configuration/McpOptions.cs index 4306eef..d1b0dd6 100644 --- a/src/Microsoft.Azure.Functions.Extensions.Mcp/Configuration/McpOptions.cs +++ b/src/Microsoft.Azure.Functions.Extensions.Mcp/Configuration/McpOptions.cs @@ -1,12 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Microsoft.Azure.WebJobs.Hosting; +using Newtonsoft.Json.Linq; +using System.ComponentModel; + namespace Microsoft.Azure.Functions.Extensions.Mcp.Configuration; /// /// Options for configuring the Model Context Protocol (MCP) extension in Azure Functions. /// -public sealed class McpOptions +public sealed class McpOptions : IOptionsFormatter { private MessageOptions _messageOptions = new(); @@ -41,4 +45,20 @@ public MessageOptions MessageOptions set => _messageOptions = value ?? throw new ArgumentNullException(nameof(value),"Message options cannot be null."); } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + string IOptionsFormatter.Format() + { + JObject options = new JObject + { + { nameof(ServerName), ServerName }, + { nameof(ServerVersion), ServerVersion }, + { nameof(Instructions), Instructions }, + { nameof(EncryptClientState), EncryptClientState }, + { nameof(MessageOptions) + "." + nameof(MessageOptions.UseAbsoluteUriForEndpoint), MessageOptions.UseAbsoluteUriForEndpoint } + }; + + return options.ToString(Newtonsoft.Json.Formatting.Indented); + } } \ No newline at end of file diff --git a/test/Extensions.Mcp.Tests/McpOptionsTests.cs b/test/Extensions.Mcp.Tests/McpOptionsTests.cs index 73ccd46..252a775 100644 --- a/test/Extensions.Mcp.Tests/McpOptionsTests.cs +++ b/test/Extensions.Mcp.Tests/McpOptionsTests.cs @@ -2,6 +2,8 @@ // Licensed under the MIT License. using Microsoft.Azure.Functions.Extensions.Mcp.Configuration; +using Microsoft.Azure.WebJobs.Hosting; +using Newtonsoft.Json.Linq; using Xunit; namespace Microsoft.Azure.Functions.Extensions.Mcp.Tests; @@ -20,4 +22,45 @@ public void DefaultValues_AreSetCorrectly() Assert.NotNull(options.MessageOptions); Assert.False(options.MessageOptions.UseAbsoluteUriForEndpoint); } + + [Fact] + public void Format_ReturnsExpectedJson() + { + var options = new McpOptions + { + ServerName = "Test Server", + ServerVersion = "2.0.0", + Instructions = "Test instructions", + EncryptClientState = false + }; + options.MessageOptions.UseAbsoluteUriForEndpoint = true; + + var formatter = (IOptionsFormatter)options; + var formatted = formatter.Format(); + + Assert.NotNull(formatted); + + var json = JObject.Parse(formatted); + Assert.Equal("Test Server", json[nameof(options.ServerName)]?.ToString()); + Assert.Equal("2.0.0", json[nameof(options.ServerVersion)]?.ToString()); + Assert.Equal("Test instructions", json[nameof(options.Instructions)]?.ToString()); + Assert.Equal("False", json[nameof(options.EncryptClientState)]?.ToString()); + Assert.Equal("True", json["MessageOptions.UseAbsoluteUriForEndpoint"]?.ToString()); + } + + [Fact] + public void Format_IncludesAllNonSensitiveProperties() + { + var options = new McpOptions(); + var formatter = (IOptionsFormatter)options; + var formatted = formatter.Format(); + + var json = JObject.Parse(formatted); + + Assert.Contains(nameof(options.ServerName), json.Properties().Select(p => p.Name)); + Assert.Contains(nameof(options.ServerVersion), json.Properties().Select(p => p.Name)); + Assert.Contains(nameof(options.Instructions), json.Properties().Select(p => p.Name)); + Assert.Contains(nameof(options.EncryptClientState), json.Properties().Select(p => p.Name)); + Assert.Contains("MessageOptions.UseAbsoluteUriForEndpoint", json.Properties().Select(p => p.Name)); + } } \ No newline at end of file