From 5ddbd40bd5dfaac0218ab50124c37a6cbaa52c3f Mon Sep 17 00:00:00 2001 From: Loi Nguyen Date: Sun, 19 Jul 2026 20:53:26 +0700 Subject: [PATCH] Add MCP Apps to NativeAOT coverage --- ...xtProtocol.AotCompatibility.TestApp.csproj | 6 ++- .../Program.cs | 38 +++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/tests/ModelContextProtocol.AotCompatibility.TestApp/ModelContextProtocol.AotCompatibility.TestApp.csproj b/tests/ModelContextProtocol.AotCompatibility.TestApp/ModelContextProtocol.AotCompatibility.TestApp.csproj index 2b505f9ed..dd3decb72 100644 --- a/tests/ModelContextProtocol.AotCompatibility.TestApp/ModelContextProtocol.AotCompatibility.TestApp.csproj +++ b/tests/ModelContextProtocol.AotCompatibility.TestApp/ModelContextProtocol.AotCompatibility.TestApp.csproj @@ -7,18 +7,20 @@ true false - - $(NoWarn);MCPEXP001 + + $(NoWarn);MCPEXP001;MCPEXP003 + + diff --git a/tests/ModelContextProtocol.AotCompatibility.TestApp/Program.cs b/tests/ModelContextProtocol.AotCompatibility.TestApp/Program.cs index 687d78e4e..708cd9361 100644 --- a/tests/ModelContextProtocol.AotCompatibility.TestApp/Program.cs +++ b/tests/ModelContextProtocol.AotCompatibility.TestApp/Program.cs @@ -1,17 +1,20 @@ +using Microsoft.Extensions.DependencyInjection; using ModelContextProtocol.Client; +using ModelContextProtocol.Extensions.Apps; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; using System.IO.Pipelines; Pipe clientToServerPipe = new(), serverToClientPipe = new(); -// Create a server using a stream-based transport over an in-memory pipe. -await using McpServer server = McpServer.Create( - new StreamServerTransport(clientToServerPipe.Reader.AsStream(), serverToClientPipe.Writer.AsStream()), - new McpServerOptions() - { - ToolCollection = [McpServerTool.Create((string arg) => $"Echo: {arg}", new() { Name = "Echo" })] - }); +var services = new ServiceCollection(); +services.AddMcpServer() + .WithStreamServerTransport(clientToServerPipe.Reader.AsStream(), serverToClientPipe.Writer.AsStream()) + .WithTools() + .WithMcpApps(); + +await using var serviceProvider = services.BuildServiceProvider(); +var server = serviceProvider.GetRequiredService(); _ = server.RunAsync(); // Connect a client using a stream-based transport over the same in-memory pipe. @@ -20,13 +23,18 @@ // List all tools. var tools = await client.ListToolsAsync(); -if (tools.Count == 0) +var echo = tools.FirstOrDefault(t => t.Name == "Echo"); +if (echo is null) +{ + throw new Exception("Expected the Echo tool."); +} + +var ui = echo.ProtocolTool.Meta?["ui"]?.AsObject(); +if (ui?["resourceUri"]?.GetValue() != "ui://aot/echo") { - throw new Exception("Expected at least one tool."); + throw new Exception($"Unexpected app UI metadata: {ui}"); } -// Invoke a tool. -var echo = tools.First(t => t.Name == "Echo"); var result = await echo.InvokeAsync(new() { ["arg"] = "Hello World" }); if (result is null || !result.ToString()!.Contains("Echo: Hello World")) { @@ -34,3 +42,11 @@ } Console.WriteLine("Success!"); + +[McpServerToolType] +internal sealed class AotTools +{ + [McpServerTool(Name = "Echo")] + [McpAppUi(ResourceUri = "ui://aot/echo")] + public static string Echo(string arg) => $"Echo: {arg}"; +}