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);
}
}
}
}
}