Mark samples as AOT compatible (#184)

* Revert changes to remove APIs

* Apply suggestions from code review

Co-authored-by: Stephen Toub <stoub@microsoft.com>

---------

Co-authored-by: Stephen Toub <stoub@microsoft.com>
This commit is contained in:
Andy Gocke 2025-04-03 11:12:25 -07:00 • committed by GitHub
commit f652b1a03d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 51 additions and 10 deletions

View file

@ -4,6 +4,7 @@
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<PublishAot>true</PublishAot>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,5 +1,10 @@
using TestServerWithHosting.Tools;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer().WithToolsFromAssembly(); builder.Services.AddMcpServer()
.WithTools<EchoTool>()
.WithTools<SampleLlmTool>();
var app = builder.Build(); var app = builder.Build();
app.MapMcp(); app.MapMcp();

View file

@ -4,7 +4,7 @@ using System.ComponentModel;
namespace TestServerWithHosting.Tools; namespace TestServerWithHosting.Tools;
[McpServerToolType] [McpServerToolType]
public static class EchoTool public sealed class EchoTool
{ {
[McpServerTool, Description("Echoes the input back to the client.")] [McpServerTool, Description("Echoes the input back to the client.")]
public static string Echo(string message) public static string Echo(string message)

View file

@ -8,7 +8,7 @@ namespace TestServerWithHosting.Tools;
/// This tool uses dependency injection and async method /// This tool uses dependency injection and async method
/// </summary> /// </summary>
[McpServerToolType] [McpServerToolType]
public static class SampleLlmTool public sealed class SampleLlmTool
{ {
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")] [McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
public static async Task<string> SampleLLM( public static async Task<string> SampleLLM(

View file

@ -5,6 +5,10 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<!--
Anthropic SDK isn't AOT compatible yet
<PublishAot>true</PublishAot>
-->
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -6,6 +6,10 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<UserSecretsId>a4e20a70-5009-4b81-b5b6-780b6d43e78e</UserSecretsId> <UserSecretsId>a4e20a70-5009-4b81-b5b6-780b6d43e78e</UserSecretsId>
<!--
Anthropic SDK isn't AOT compatible yet
<PublishAot>true</PublishAot>
-->
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,13 +1,14 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using QuickstartWeatherServer.Tools;
using System.Net.Http.Headers; using System.Net.Http.Headers;
var builder = Host.CreateApplicationBuilder(args); var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMcpServer() builder.Services.AddMcpServer()
.WithStdioServerTransport() .WithStdioServerTransport()
.WithToolsFromAssembly(); .WithTools<WeatherTools>();
builder.Logging.AddConsole(options => builder.Logging.AddConsole(options =>
{ {

View file

@ -5,6 +5,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -0,0 +1,13 @@
using System.Text.Json;
namespace ModelContextProtocol;
internal static class HttpClientExt
{
public static async Task<JsonDocument> ReadJsonDocumentAsync(this HttpClient client, string requestUri)
{
using var response = await client.GetAsync(requestUri);
response.EnsureSuccessStatusCode();
return await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
}
}

View file

@ -1,3 +1,4 @@
using ModelContextProtocol;
using ModelContextProtocol.Server; using ModelContextProtocol.Server;
using System.ComponentModel; using System.ComponentModel;
using System.Net.Http.Json; using System.Net.Http.Json;
@ -6,14 +7,15 @@ using System.Text.Json;
namespace QuickstartWeatherServer.Tools; namespace QuickstartWeatherServer.Tools;
[McpServerToolType] [McpServerToolType]
public static class WeatherTools public sealed class WeatherTools
{ {
[McpServerTool, Description("Get weather alerts for a US state.")] [McpServerTool, Description("Get weather alerts for a US state.")]
public static async Task<string> GetAlerts( public static async Task<string> GetAlerts(
HttpClient client, HttpClient client,
[Description("The US state to get alerts for.")] string state) [Description("The US state to get alerts for.")] string state)
{ {
var jsonElement = await client.GetFromJsonAsync<JsonElement>($"/alerts/active/area/{state}"); using var jsonDocument = await client.ReadJsonDocumentAsync($"/alerts/active/area/{state}");
var jsonElement = jsonDocument.RootElement;
var alerts = jsonElement.GetProperty("features").EnumerateArray(); var alerts = jsonElement.GetProperty("features").EnumerateArray();
if (!alerts.Any()) if (!alerts.Any())
@ -40,7 +42,8 @@ public static class WeatherTools
[Description("Latitude of the location.")] double latitude, [Description("Latitude of the location.")] double latitude,
[Description("Longitude of the location.")] double longitude) [Description("Longitude of the location.")] double longitude)
{ {
var jsonElement = await client.GetFromJsonAsync<JsonElement>($"/points/{latitude},{longitude}"); using var jsonDocument = await client.ReadJsonDocumentAsync($"/points/{latitude},{longitude}");
var jsonElement = jsonDocument.RootElement;
var periods = jsonElement.GetProperty("properties").GetProperty("periods").EnumerateArray(); var periods = jsonElement.GetProperty("properties").GetProperty("periods").EnumerateArray();
return string.Join("\n---\n", periods.Select(period => $""" return string.Join("\n---\n", periods.Select(period => $"""

View file

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Serilog; using Serilog;
using TestServerWithHosting.Tools;
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose() // Capture all log levels .MinimumLevel.Verbose() // Capture all log levels
@ -19,7 +20,8 @@ try
builder.Services.AddSerilog(); builder.Services.AddSerilog();
builder.Services.AddMcpServer() builder.Services.AddMcpServer()
.WithStdioServerTransport() .WithStdioServerTransport()
.WithToolsFromAssembly(); .WithTools<EchoTool>()
.WithTools<SampleLlmTool>();
var app = builder.Build(); var app = builder.Build();

View file

@ -5,6 +5,10 @@
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<!--
Serilog AOT support regressed
<PublishAot>true</PublishAot>
-->
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -13,6 +17,9 @@
<PackageReference Include="Serilog.Sinks.Console" /> <PackageReference Include="Serilog.Sinks.Console" />
<PackageReference Include="Serilog.Sinks.Debug" /> <PackageReference Include="Serilog.Sinks.Debug" />
<PackageReference Include="Serilog.Sinks.File" /> <PackageReference Include="Serilog.Sinks.File" />
<RuntimeHostConfigurationOption
Include="Serilog.IsCompilerGeneratedCodeSupported"
Value="false" Trim="true" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -4,7 +4,7 @@ using System.ComponentModel;
namespace TestServerWithHosting.Tools; namespace TestServerWithHosting.Tools;
[McpServerToolType] [McpServerToolType]
public static class EchoTool public sealed class EchoTool
{ {
[McpServerTool, Description("Echoes the input back to the client.")] [McpServerTool, Description("Echoes the input back to the client.")]
public static string Echo(string message) public static string Echo(string message)

View file

@ -8,7 +8,7 @@ namespace TestServerWithHosting.Tools;
/// This tool uses depenency injection and async method /// This tool uses depenency injection and async method
/// </summary> /// </summary>
[McpServerToolType] [McpServerToolType]
public static class SampleLlmTool public sealed class SampleLlmTool
{ {
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")] [McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
public static async Task<string> SampleLLM( public static async Task<string> SampleLLM(