Building a Dual-Transport MCP Server with .NET: STDIO and HTTP Support
justinyoo explains how to implement a .NET MCP server with runtime-selectable STDIO and HTTP transports, reducing management overhead and supporting integration with Copilot Studio and other platforms.
Building a Dual-Transport MCP Server with .NET: STDIO and HTTP Support
Author: justinyoo
This guide will show you how to build a single Model Context Protocol (MCP) server that can operate using either STDIO (console) or HTTP transports, selectable with a simple --http
command-line switch. The approach leverages the .NET builder pattern to avoid code duplication and simplify deployment, supporting integration scenarios such as with Copilot Studio or enterprise solutions where HTTP may be required.
Why Dual-Transport MCP Servers?
- Flexibility: Run MCP servers locally (STDIO) or across networks (HTTP) without modifying core logic.
- Maintainability: Minimize code duplication by sharing core logic and abstracting transport selection.
- Integration: Easily integrate with tooling like Copilot Studio or enable secure, remote access via HTTP.
Using the .NET Builder Pattern
There are two primary .NET builder interfaces:
-
Console apps use:
var builder = Host.CreateApplicationBuilder(args);
-
ASP.NET web apps use:
var builder = WebApplication.CreateBuilder(args);
Both result in a builder implementing IHostApplicationBuilder
, giving a common ground for adding services and logic prior to selecting the hosting mode.
Mode Selection at Runtime
Determine the transport mode via argument or environment variable:
dotnet run --project MyMcpServer -- --http
Check for --http
in the arguments or UseHttp
in environment variables:
public static bool UseStreamableHttp(IDictionary env, string[] args) {
var useHttp = env.Contains("UseHttp") && bool.TryParse(env["UseHttp"]?.ToString()?.ToLowerInvariant(), out var result) && result;
if (args.Length == 0) return useHttp;
useHttp = args.Contains("--http", StringComparer.InvariantCultureIgnoreCase);
return useHttp;
}
Use this selector to choose the builder:
IHostApplicationBuilder builder = useStreamableHttp
? WebApplication.CreateBuilder(args)
: Host.CreateApplicationBuilder(args);
Registering the MCP Server
Add your MCP server and related services to the DI container:
var mcpServerBuilder = builder.Services.AddMcpServer()
.WithPromptsFromAssembly()
.WithResourcesFromAssembly()
.WithToolsFromAssembly();
Select the correct transport based on the runtime check:
if (useStreamableHttp) {
mcpServerBuilder.WithHttpTransport(o => o.Stateless = true);
} else {
mcpServerBuilder.WithStdioServerTransport();
}
Bootstrapping and Running the Server
Depending on the hosting mode, cast and build appropriately:
IHost app;
if (useStreamableHttp) {
var webApp = (builder as WebApplicationBuilder)!.Build();
webApp.UseHttpsRedirection();
webApp.MapMcp("/mcp");
app = webApp;
} else {
var consoleApp = (builder as HostApplicationBuilder)!.Build();
app = consoleApp;
}
await app.RunAsync();
Sample Code and Additional Resources
- MCP Samples in .NET
- Let’s Learn MCP
- MCP Workshop in .NET
- MCP for Beginners
- Copilot Studio integration
This technique enables efficient and maintainable MCP server deployments in .NET for both local development and broader enterprise integration scenarios.
This post appeared first on “Microsoft Tech Community”. Read the entire article here