using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; using System.Diagnostics.CodeAnalysis; namespace ModelContextProtocol.Extensions.Apps; /// /// Extension methods for to enable MCP Apps support. /// [Experimental(Experimentals.Apps_DiagnosticId, UrlFormat = Experimentals.Apps_Url)] public static class McpAppsBuilderExtensions { /// /// Enables MCP Apps support by automatically processing on registered tools. /// /// The server builder. /// The builder provided in . /// /// /// Call this method after registering tools (e.g., after WithTools<T>()) to automatically /// apply metadata to the tool's _meta.ui field. /// /// /// Tools that already have a ui key in their (e.g., set explicitly /// via ) are not modified. /// /// /// /// /// builder.Services /// .AddMcpServer() /// .WithTools<MyToolType>() /// .WithMcpApps(); /// /// public static IMcpServerBuilder WithMcpApps(this IMcpServerBuilder builder) { #if NET ArgumentNullException.ThrowIfNull(builder); #else if (builder is null) throw new ArgumentNullException(nameof(builder)); #endif builder.Services.AddSingleton, McpAppsPostConfigureOptions>(); return builder; } private sealed class McpAppsPostConfigureOptions : IPostConfigureOptions { public void PostConfigure(string? name, McpServerOptions options) { // Advertise server-side MCP Apps support in capabilities. options.Capabilities ??= new ServerCapabilities(); options.Capabilities.Extensions ??= new Dictionary(); if (!options.Capabilities.Extensions.ContainsKey(McpApps.ExtensionId)) { options.Capabilities.Extensions[McpApps.ExtensionId] = new System.Text.Json.Nodes.JsonObject(); } if (options.ToolCollection is { IsEmpty: false } tools) { foreach (var tool in tools) { McpApps.ApplyAppUiAttributes(tool); } } } } }