Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion ModelContextProtocol.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
<Project Path="samples/ProtectedMcpClient/ProtectedMcpClient.csproj" />
<Project Path="samples/ProtectedMcpServer/ProtectedMcpServer.csproj" />
<Project Path="samples/QuickstartClient/QuickstartClient.csproj" />
<Project Path="samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj" />
<Project Path="samples/TestServerWithHosting/TestServerWithHosting.csproj" />
</Folder>
<Folder Name="/Solution Items/">
Expand Down
30 changes: 0 additions & 30 deletions samples/FileBasedMcpServer/Program.cs

This file was deleted.

64 changes: 0 additions & 64 deletions samples/FileBasedMcpServer/README.md

This file was deleted.

2 changes: 1 addition & 1 deletion samples/InMemoryTransport/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using ModelContextProtocol.Client;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using System.IO.Pipelines;
Expand Down
75 changes: 74 additions & 1 deletion samples/QuickstartWeatherServer/Program.cs
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#!/usr/bin/env -S dotnet run --
#:package Microsoft.Extensions.Hosting
#:project ../../src/ModelContextProtocol/ModelContextProtocol.csproj

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using QuickstartWeatherServer.Tools;
using ModelContextProtocol;
using ModelContextProtocol.Server;
using System.ComponentModel;
using System.Globalization;
using System.Net.Http.Headers;
using System.Text.Json;

var builder = Host.CreateApplicationBuilder(args);

Expand All @@ -20,3 +28,68 @@
builder.Services.AddSingleton(httpClient);

await builder.Build().RunAsync();

// Weather Tools
[McpServerToolType]
file sealed class WeatherTools
{
[McpServerTool, Description("Get weather alerts for a US state.")]
public static async Task<string> GetAlerts(
HttpClient client,
[Description("The US state to get alerts for. Use the 2 letter abbreviation for the state (e.g. NY).")] string state)
{
using var jsonDocument = await client.ReadJsonDocumentAsync($"/alerts/active/area/{state}");
var jsonElement = jsonDocument.RootElement;
var alerts = jsonElement.GetProperty("features").EnumerateArray();

if (!alerts.Any())
{
return "No active alerts for this state.";
}

return string.Join("\n--\n", alerts.Select(alert =>
{
JsonElement properties = alert.GetProperty("properties");
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()}
""";
}));
}

[McpServerTool, Description("Get weather forecast for a location.")]
public static async Task<string> GetForecast(
HttpClient client,
[Description("Latitude of the location.")] double latitude,
[Description("Longitude of the location.")] double longitude)
{
var pointUrl = string.Create(CultureInfo.InvariantCulture, $"/points/{latitude},{longitude}");
using var locationDocument = await client.ReadJsonDocumentAsync(pointUrl);
var forecastUrl = locationDocument.RootElement.GetProperty("properties").GetProperty("forecast").GetString()
?? throw new McpException($"No forecast URL provided by {client.BaseAddress}points/{latitude},{longitude}");

using var forecastDocument = await client.ReadJsonDocumentAsync(forecastUrl);
var periods = forecastDocument.RootElement.GetProperty("properties").GetProperty("periods").EnumerateArray();

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

// HttpClient Extension Methods
file 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());
}
}
19 changes: 0 additions & 19 deletions samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj

This file was deleted.

61 changes: 61 additions & 0 deletions samples/QuickstartWeatherServer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# QuickstartWeatherServer Sample

This sample demonstrates how to create an MCP server that provides weather-related tools using the weather.gov API. This is a file-based program that runs without a traditional project file.

## Requirements

- .NET 8.0 SDK or later
- No project file required!

## Running the Sample

Simply run the Program.cs file directly:

```bash
dotnet run Program.cs
```

Or on Unix-like systems, make the file executable:

```bash
chmod +x Program.cs
./Program.cs
```

The server will start and listen for MCP messages on stdin/stdout (stdio transport).

## Available Tools

The server provides two weather tools:

1. **GetAlerts** - Get weather alerts for a US state (use 2-letter abbreviation like "NY")
2. **GetForecast** - Get weather forecast for a location (requires latitude and longitude)

## Testing the Server

You can test the server using the QuickstartClient or any MCP-compatible client:

```bash
# From the repository root
dotnet run --project samples/QuickstartClient samples/QuickstartWeatherServer
```

Or test with the MCP inspector:

```bash
npx @modelcontextprotocol/inspector dotnet run Program.cs
```

## What This Sample Shows

- Creating an MCP server using `Host.CreateApplicationBuilder`
- Registering tools with `WithTools<T>()`
- Using dependency injection to provide HttpClient to tools
- Configuring logging to stderr for MCP compatibility
- Using file-scoped classes for tool implementations

## Reference

- [File-Based Programs Tutorial](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/file-based-programs)
- [Model Context Protocol Specification](https://modelcontextprotocol.io/specification/)
- [Weather.gov API](https://www.weather.gov/documentation/services-web-api)
13 changes: 0 additions & 13 deletions samples/QuickstartWeatherServer/Tools/HttpClientExt.cs

This file was deleted.

60 changes: 0 additions & 60 deletions samples/QuickstartWeatherServer/Tools/WeatherTools.cs

This file was deleted.

Loading