One MCP Server, Two Transports: STDIO and HTTP
justinyoo details how to build a .NET MCP server capable of handling both STDIO and HTTP transports using the builder pattern and a runtime switch, streamlining server management and flexibility.
One MCP Server, Two Transports: STDIO and HTTP
In this tutorial, justinyoo demonstrates how to build a single MCP (Model Context Protocol) server in .NET that supports both STDIO and HTTP transports, allowing the hosting mode to be switched at runtime with a simple --http
flag. This reduces the management overhead of maintaining separate codebases or hosts for each transport.
When to Use MCP Servers
- Most MCP servers run locally (directly or in containers).
- Integration scenarios like Copilot Studio, or secure environments, often require remote HTTP-based servers.
Design Goal
Support both STDIO and HTTP with a single server instance, switching modes with a --http
command-line argument rather than duplicating code.
Using the .NET Builder Pattern
- Start with either a console app builder or a web app builder, depending on the hosting mode.
- Interface in common:
IHostApplicationBuilder
.
Console Application:
var builder = Host.CreateApplicationBuilder(args);
Web Application:
var builder = WebApplication.CreateBuilder(args);
Determining Hosting Mode
A command-line switch, --http
, determines which builder to use:
Example:
dotnet run --project MyMcpServer -- --http
Function to select transport:
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;
}
Using the selector:
var useStreamableHttp = UseStreamableHttp(Environment.GetEnvironmentVariables(), args);
IHostApplicationBuilder builder = useStreamableHttp ? WebApplication.CreateBuilder(args) : Host.CreateApplicationBuilder(args);
Configuring the MCP Server
Add dependencies to the builder, import prompts, resources, and tools:
var mcpServerBuilder = builder.Services.AddMcpServer()
.WithPromptsFromAssembly()
.WithResourcesFromAssembly()
.WithToolsFromAssembly();
Select the transport based on the switch:
if (useStreamableHttp) {
mcpServerBuilder.WithHttpTransport(o => o.Stateless = true);
} else {
mcpServerBuilder.WithStdioServerTransport();
}
Running the Server
Cast to the appropriate host type and run the server:
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 Apps and Resources
By following this approach, developers can manage a single, versatile MCP server project in .NET, simplifying deployment and integration with various platforms.
This post appeared first on “Microsoft Tech Community”. Read the entire article here