diff --git a/quickstart/client.mdx b/quickstart/client.mdx index 68e61da..c98984b 100644 --- a/quickstart/client.mdx +++ b/quickstart/client.mdx @@ -1384,7 +1384,7 @@ cd QuickstartClient Then, add the required dependencies to your project: ```bash -dotnet add package ModelContextProtocol --preview +dotnet add package ModelContextProtocol --prerelease dotnet add package Anthropic.SDK dotnet add package Microsoft.Extensions.Hosting ``` @@ -1423,10 +1423,10 @@ var (command, arguments) = args switch _ => throw new NotSupportedException("An unsupported server script was provided. Supported scripts are .py, .js, or .csproj") }; -var mcpClient = await McpClientFactory.CreateAsync(new() +await using var mcpClient = await McpClientFactory.CreateAsync(new() { - Id = "demo-client", - Name = "Demo Client", + Id = "demo-server", + Name = "Demo Server", TransportType = TransportTypes.StdIo, TransportOptions = new() { @@ -1455,7 +1455,7 @@ This configures a MCP client that will connect to a server that is provided as a Now let's add the core functionality for processing queries and handling tool calls: ```csharp -IChatClient anthropicClient = new AnthropicClient(new APIAuthentication(builder.Configuration["ANTHROPIC_API_KEY"])) +using IChatClient anthropicClient = new AnthropicClient(new APIAuthentication(builder.Configuration["ANTHROPIC_API_KEY"])) .Messages .AsBuilder() .UseFunctionInvocation() @@ -1465,7 +1465,7 @@ var options = new ChatOptions { MaxOutputTokens = 1000, ModelId = "claude-3-5-sonnet-20241022", - Tools = [.. tools.Cast()] + Tools = [.. tools] }; while (true) @@ -1484,16 +1484,14 @@ while (true) break; } - var response = await anthropicClient.GetResponseAsync(query, options); + var response = anthropicClient.GetStreamingResponseAsync(query, options); - foreach (var message in response.Messages) + await foreach (var message in response) { - Console.WriteLine(message.Text); + Console.Write(message.Text); } + Console.WriteLine(); } - -anthropicClient.Dispose(); -await mcpClient.DisposeAsync(); ``` ## Key Components Explained diff --git a/quickstart/server.mdx b/quickstart/server.mdx index 57767a5..920cc80 100644 --- a/quickstart/server.mdx +++ b/quickstart/server.mdx @@ -1450,7 +1450,7 @@ After creating the project, add NuGet package for the Model Context Protocol SDK ```bash # Add the Model Context Protocol SDK NuGet package -dotnet add package ModelContextProtocol --preview +dotnet add package ModelContextProtocol --prerelease # Add the .NET Hosting NuGet package dotnet add package Microsoft.Extensions.Hosting ``` @@ -1461,14 +1461,24 @@ Now let’s dive into building your server. Open the `Program.cs` file in your project and replace its contents with the following code: ```csharp +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using ModelContextProtocol; +using System.Net.Http.Headers; var builder = Host.CreateEmptyApplicationBuilder(settings: null); + builder.Services.AddMcpServer() .WithStdioServerTransport() .WithToolsFromAssembly(); +builder.Services.AddSingleton(_ => +{ + var client = new HttpClient() { BaseAddress = new Uri("https://api.weather.gov") }; + client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("weather-tool", "1.0")); + return client; +}); + var app = builder.Build(); await app.RunAsync(); @@ -1485,7 +1495,7 @@ Next, define a class with the tool execution handlers for querying and convertin ```csharp using ModelContextProtocol.Server; using System.ComponentModel; -using System.Net.Http.Headers; +using System.Net.Http.Json; using System.Text.Json; namespace QuickstartWeatherServer.Tools; @@ -1495,14 +1505,10 @@ public static class WeatherTools { [McpServerTool, Description("Get weather alerts for a US state.")] public static async Task GetAlerts( + HttpClient client, [Description("The US state to get alerts for.")] string state) { - using HttpClient client = GetWeatherClient(); - - var response = await client.GetAsync($"/alerts/active/area/{state}"); - - var json = await response.Content.ReadAsStringAsync(); - var jsonElement = JsonSerializer.Deserialize(json); + var jsonElement = await client.GetFromJsonAsync($"/alerts/active/area/{state}"); var alerts = jsonElement.GetProperty("features").EnumerateArray(); if (!alerts.Any()) @@ -1510,56 +1516,34 @@ public static class WeatherTools return "No active alerts for this state."; } - // Process the alerts and return a formatted string - var alertMessages = new List(); - foreach (var alert in alerts) + return string.Join("\n--\n", alerts.Select(alert => { JsonElement properties = alert.GetProperty("properties"); - alertMessages.Add($""" + return $""" Event: {properties.GetProperty("event").GetString()} Area: {properties.GetProperty("areaDesc").GetString()} Severity: {properties.GetProperty("severity").GetString()} Description: {properties.GetProperty("description").GetString()} Instruction: {properties.GetProperty("instruction").GetString()} - """); - } - return string.Join("\n---\n", alertMessages); + """; + })); } [McpServerTool, Description("Get weather forecast for a location.")] public static async Task GetForecast( + HttpClient client, [Description("Latitude of the location.")] double latitude, [Description("Longitude of the location.")] double longitude) { - using HttpClient client = GetWeatherClient(); - var response = await client.GetAsync($"/points/{latitude},{longitude}"); - if (!response.IsSuccessStatusCode) - { - return "Failed to retrieve forecast."; - } - - var json = await response.Content.ReadAsStringAsync(); - var jsonElement = JsonSerializer.Deserialize(json); + var jsonElement = await client.GetFromJsonAsync($"/points/{latitude},{longitude}"); var periods = jsonElement.GetProperty("properties").GetProperty("periods").EnumerateArray(); - // Process the forecast and return a formatted string - var forecastMessages = new List(); - foreach (var period in periods) - { - forecastMessages.Add($""" - {period.GetProperty("name").GetString()} - Temperature: {period.GetProperty("temperature").GetInt32()}°F - Wind: {period.GetProperty("windSpeed").GetString()} {period.GetProperty("windDirection").GetString()} - Forecast: {period.GetProperty("detailedForecast").GetString()} - """); - } - return string.Join("\n---\n", forecastMessages); - } - private static HttpClient GetWeatherClient() - { - var client = new HttpClient() { BaseAddress = new Uri("https://api.weather.gov") }; - client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("weather-tool", "1.0")); - return client; + return string.Join("\n---\n", periods.Select(period => $""" + {period.GetProperty("name").GetString()} + Temperature: {period.GetProperty("temperature").GetInt32()}°F + Wind: {period.GetProperty("windSpeed").GetString()} {period.GetProperty("windDirection").GetString()} + Forecast: {period.GetProperty("detailedForecast").GetString()} + """)); } } ```