From 5644a9829075fd4dfa52364d228da2a432b43a14 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 24 Nov 2025 08:52:28 +0000
Subject: [PATCH 1/4] Initial plan
From fd5632165f947f17e6aea6592982d166c7f6a3f4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 24 Nov 2025 09:04:59 +0000
Subject: [PATCH 2/4] Convert InMemoryTransport and QuickstartWeatherServer to
file-based projects, delete FileBasedMcpServer
Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>
---
ModelContextProtocol.slnx | 2 -
samples/FileBasedMcpServer/Program.cs | 30 --------
samples/FileBasedMcpServer/README.md | 64 ----------------
.../InMemoryTransport.csproj | 15 ----
samples/InMemoryTransport/Program.cs | 5 +-
samples/InMemoryTransport/README.md | 37 +++++++++
samples/QuickstartWeatherServer/Program.cs | 75 ++++++++++++++++++-
.../QuickstartWeatherServer.csproj | 19 -----
samples/QuickstartWeatherServer/README.md | 61 +++++++++++++++
.../Tools/HttpClientExt.cs | 13 ----
.../Tools/WeatherTools.cs | 60 ---------------
11 files changed, 176 insertions(+), 205 deletions(-)
delete mode 100755 samples/FileBasedMcpServer/Program.cs
delete mode 100644 samples/FileBasedMcpServer/README.md
delete mode 100644 samples/InMemoryTransport/InMemoryTransport.csproj
create mode 100644 samples/InMemoryTransport/README.md
delete mode 100644 samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj
create mode 100644 samples/QuickstartWeatherServer/README.md
delete mode 100644 samples/QuickstartWeatherServer/Tools/HttpClientExt.cs
delete mode 100644 samples/QuickstartWeatherServer/Tools/WeatherTools.cs
diff --git a/ModelContextProtocol.slnx b/ModelContextProtocol.slnx
index 1f6dce1ed..44ea426f1 100644
--- a/ModelContextProtocol.slnx
+++ b/ModelContextProtocol.slnx
@@ -43,11 +43,9 @@
-
-
diff --git a/samples/FileBasedMcpServer/Program.cs b/samples/FileBasedMcpServer/Program.cs
deleted file mode 100755
index daf9464d1..000000000
--- a/samples/FileBasedMcpServer/Program.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/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 ModelContextProtocol.Server;
-using System.ComponentModel;
-
-var builder = Host.CreateApplicationBuilder(args);
-
-builder.Services.AddMcpServer()
- .WithStdioServerTransport()
- .WithTools();
-
-builder.Logging.AddConsole(options =>
-{
- options.LogToStandardErrorThreshold = LogLevel.Trace;
-});
-
-await builder.Build().RunAsync();
-
-// File-scoped tool class
-[McpServerToolType]
-file class EchoTool
-{
- [McpServerTool(Name = "echo"), Description("Echoes the message back to the client.")]
- public static string Echo([Description("The message to echo back.")] string message) => $"Echo: {message}";
-}
diff --git a/samples/FileBasedMcpServer/README.md b/samples/FileBasedMcpServer/README.md
deleted file mode 100644
index b28c9298d..000000000
--- a/samples/FileBasedMcpServer/README.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# File-Based MCP Server Sample
-
-This sample demonstrates how to create a complete MCP (Model Context Protocol) server using .NET 10's file-based programs feature. Unlike traditional .NET projects that require a `.csproj` file, file-based programs allow you to write and run complete applications in a single `.cs` file.
-
-## Requirements
-
-- .NET 10 SDK (RC2 or later)
-- No project file required!
-
-## Running the Sample
-
-Simply run the Program.cs file directly:
-
-```bash
-dotnet run Program.cs
-```
-
-The server will start and listen for MCP messages on stdin/stdout (stdio transport).
-
-### Making it Executable (Unix/Linux/macOS)
-
-On Unix-like systems, you can make the file executable:
-
-```bash
-chmod +x Program.cs
-./Program.cs
-```
-
-Note: The shebang line uses `/usr/bin/env` to locate `dotnet`, so ensure it's in your PATH.
-
-## Testing the Server
-
-You can test the server by using `@modelcontextprotocol/inspector`, any stdio-compatible client, or sending JSON-RPC messages to stdin. Here's an example:
-
-### Initialize the server:
-```bash
-echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0"}}}' | dotnet run Program.cs
-```
-
-### List available tools:
-```bash
-(
- echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0"}}}'
- sleep 0.5
- echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
- sleep 1
-) | dotnet run Program.cs 2>/dev/null | grep '^{' | jq .
-```
-
-### Call the echo tool:
-```bash
-(
- echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0"}}}'
- sleep 0.5
- echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"echo","arguments":{"message":"Hello, MCP!"}}}'
- sleep 1
-) | dotnet run Program.cs 2>/dev/null | grep '^{' | jq .
-```
-
-## Reference
-
-- [File-Based Programs Tutorial](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/file-based-programs)
-- [C# Preprocessor Directives for File-Based Apps](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#file-based-apps)
-- [Model Context Protocol Specification](https://modelcontextprotocol.io/specification/)
diff --git a/samples/InMemoryTransport/InMemoryTransport.csproj b/samples/InMemoryTransport/InMemoryTransport.csproj
deleted file mode 100644
index 7c1161ce9..000000000
--- a/samples/InMemoryTransport/InMemoryTransport.csproj
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- Exe
- net8.0
- enable
- enable
- true
-
-
-
-
-
-
-
diff --git a/samples/InMemoryTransport/Program.cs b/samples/InMemoryTransport/Program.cs
index dbffaa34d..b965b5bb6 100644
--- a/samples/InMemoryTransport/Program.cs
+++ b/samples/InMemoryTransport/Program.cs
@@ -1,4 +1,7 @@
-using ModelContextProtocol.Client;
+#!/usr/bin/env -S dotnet run --
+#:project ../../src/ModelContextProtocol/ModelContextProtocol.csproj
+
+using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using System.IO.Pipelines;
diff --git a/samples/InMemoryTransport/README.md b/samples/InMemoryTransport/README.md
new file mode 100644
index 000000000..eac9f16d7
--- /dev/null
+++ b/samples/InMemoryTransport/README.md
@@ -0,0 +1,37 @@
+# InMemoryTransport Sample
+
+This sample demonstrates how to create an MCP client and server connected via an in-memory pipe, without using network sockets or stdio. This is useful for testing and embedding MCP servers directly in your application.
+
+## 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
+```
+
+## What This Sample Shows
+
+- Creating a server with `StreamServerTransport` over an in-memory pipe
+- Connecting a client using `StreamClientTransport` over the same pipe
+- Listing available tools from the server
+- Invoking tools on the server
+
+The sample creates a simple "Echo" tool that echoes back the input message.
+
+## 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/)
diff --git a/samples/QuickstartWeatherServer/Program.cs b/samples/QuickstartWeatherServer/Program.cs
index 9bc050b54..92ebdd02f 100644
--- a/samples/QuickstartWeatherServer/Program.cs
+++ b/samples/QuickstartWeatherServer/Program.cs
@@ -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);
@@ -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 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 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 ReadJsonDocumentAsync(this HttpClient client, string requestUri)
+ {
+ using var response = await client.GetAsync(requestUri);
+ response.EnsureSuccessStatusCode();
+ return await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
+ }
+}
diff --git a/samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj b/samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj
deleted file mode 100644
index dc1108a8f..000000000
--- a/samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- Exe
- net8.0
- enable
- enable
- true
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/QuickstartWeatherServer/README.md b/samples/QuickstartWeatherServer/README.md
new file mode 100644
index 000000000..06abd2fbf
--- /dev/null
+++ b/samples/QuickstartWeatherServer/README.md
@@ -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 samples/QuickstartWeatherServer/Program.cs
+```
+
+## What This Sample Shows
+
+- Creating an MCP server using `Host.CreateApplicationBuilder`
+- Registering tools with `WithTools()`
+- 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)
diff --git a/samples/QuickstartWeatherServer/Tools/HttpClientExt.cs b/samples/QuickstartWeatherServer/Tools/HttpClientExt.cs
deleted file mode 100644
index f7b2b5499..000000000
--- a/samples/QuickstartWeatherServer/Tools/HttpClientExt.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Text.Json;
-
-namespace ModelContextProtocol;
-
-internal static class HttpClientExt
-{
- public static async Task ReadJsonDocumentAsync(this HttpClient client, string requestUri)
- {
- using var response = await client.GetAsync(requestUri);
- response.EnsureSuccessStatusCode();
- return await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
- }
-}
\ No newline at end of file
diff --git a/samples/QuickstartWeatherServer/Tools/WeatherTools.cs b/samples/QuickstartWeatherServer/Tools/WeatherTools.cs
deleted file mode 100644
index 61dc0a0ee..000000000
--- a/samples/QuickstartWeatherServer/Tools/WeatherTools.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using ModelContextProtocol;
-using ModelContextProtocol.Server;
-using System.ComponentModel;
-using System.Globalization;
-using System.Text.Json;
-
-namespace QuickstartWeatherServer.Tools;
-
-[McpServerToolType]
-public sealed 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. 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 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()}
- """));
- }
-}
From 44a26540e0aa5c5f1c403886a95c3ab6672ee2cc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 24 Nov 2025 09:18:55 +0000
Subject: [PATCH 3/4] Revert InMemoryTransport to traditional project structure
Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>
---
ModelContextProtocol.slnx | 1 +
.../InMemoryTransport.csproj | 15 ++++++++
samples/InMemoryTransport/Program.cs | 3 --
samples/InMemoryTransport/README.md | 37 -------------------
4 files changed, 16 insertions(+), 40 deletions(-)
create mode 100644 samples/InMemoryTransport/InMemoryTransport.csproj
delete mode 100644 samples/InMemoryTransport/README.md
diff --git a/ModelContextProtocol.slnx b/ModelContextProtocol.slnx
index 44ea426f1..3ad349d47 100644
--- a/ModelContextProtocol.slnx
+++ b/ModelContextProtocol.slnx
@@ -43,6 +43,7 @@
+
diff --git a/samples/InMemoryTransport/InMemoryTransport.csproj b/samples/InMemoryTransport/InMemoryTransport.csproj
new file mode 100644
index 000000000..7c1161ce9
--- /dev/null
+++ b/samples/InMemoryTransport/InMemoryTransport.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ true
+
+
+
+
+
+
+
diff --git a/samples/InMemoryTransport/Program.cs b/samples/InMemoryTransport/Program.cs
index b965b5bb6..408ff44b4 100644
--- a/samples/InMemoryTransport/Program.cs
+++ b/samples/InMemoryTransport/Program.cs
@@ -1,6 +1,3 @@
-#!/usr/bin/env -S dotnet run --
-#:project ../../src/ModelContextProtocol/ModelContextProtocol.csproj
-
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
diff --git a/samples/InMemoryTransport/README.md b/samples/InMemoryTransport/README.md
deleted file mode 100644
index eac9f16d7..000000000
--- a/samples/InMemoryTransport/README.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# InMemoryTransport Sample
-
-This sample demonstrates how to create an MCP client and server connected via an in-memory pipe, without using network sockets or stdio. This is useful for testing and embedding MCP servers directly in your application.
-
-## 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
-```
-
-## What This Sample Shows
-
-- Creating a server with `StreamServerTransport` over an in-memory pipe
-- Connecting a client using `StreamClientTransport` over the same pipe
-- Listing available tools from the server
-- Invoking tools on the server
-
-The sample creates a simple "Echo" tool that echoes back the input message.
-
-## 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/)
From e54c0c9453848cae435c3331f396a06a1bf85536 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 24 Nov 2025 09:23:17 +0000
Subject: [PATCH 4/4] Fix README command path for QuickstartWeatherServer
Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com>
---
samples/QuickstartWeatherServer/Program.cs | 0
samples/QuickstartWeatherServer/README.md | 2 +-
2 files changed, 1 insertion(+), 1 deletion(-)
mode change 100644 => 100755 samples/QuickstartWeatherServer/Program.cs
diff --git a/samples/QuickstartWeatherServer/Program.cs b/samples/QuickstartWeatherServer/Program.cs
old mode 100644
new mode 100755
diff --git a/samples/QuickstartWeatherServer/README.md b/samples/QuickstartWeatherServer/README.md
index 06abd2fbf..4ca494d6d 100644
--- a/samples/QuickstartWeatherServer/README.md
+++ b/samples/QuickstartWeatherServer/README.md
@@ -43,7 +43,7 @@ dotnet run --project samples/QuickstartClient samples/QuickstartWeatherServer
Or test with the MCP inspector:
```bash
-npx @modelcontextprotocol/inspector dotnet run samples/QuickstartWeatherServer/Program.cs
+npx @modelcontextprotocol/inspector dotnet run Program.cs
```
## What This Sample Shows