Start Debugging

dotnet new mcpserver Now Ships in the .NET 11 Preview 4 SDK

.NET 11 Preview 4 bundles the mcpserver project template directly into the SDK. No separate Microsoft.McpServer.ProjectTemplates install, no preview feed dance. Pick stdio or HTTP transport, opt into Native AOT, and dotnet new mcpserver -o MyServer is the whole setup.

The .NET 11 Preview 4 release notes include a small but load-bearing line for anyone shipping Model Context Protocol servers from C#: the mcpserver project template, previously available only by installing Microsoft.McpServer.ProjectTemplates, now ships as a bundled template in the .NET SDK. dotnet new list discovers it without any extra install, and its servicing rides with the ASP.NET Core stack instead of a separate NuGet package.

What changes for a Preview 4 SDK

Up to .NET 11 Preview 3 the recipe for a fresh MCP server was a two-step:

# Preview 3 and earlier
dotnet new install Microsoft.McpServer.ProjectTemplates
dotnet new mcpserver -o InventoryMcp

On a clean CI image or a teammate’s first checkout, the dotnet new install step was the one that broke quietly: it pulled from NuGet, it had its own cadence, and the template lived in your user profile, which does not survive a fresh devcontainer.

With Preview 4 (11.0.100-preview.4), step one is gone:

dotnet new mcpserver -o InventoryMcp
cd InventoryMcp
dotnet run

The template is versioned with the SDK release, so a global.json pin to 11.0.100-preview.4 pins the template too.

What you actually get out of the box

dotnet new mcpserver --help exposes the knobs the template supports. The two that matter most:

dotnet new mcpserver --help

# Options:
#   -f, --framework <net11.0>            The target framework.
#   --transport <stdio|http>             MCP transport type. Default: stdio.
#   --aot                                Enable Native AOT publish.
#   --self-contained                     Enable self-contained publish.

Two real choices live here:

The --aot switch wires up Native AOT publish out of the gate: PublishAot=true in the .csproj, AOT-compatible source generators for the protocol bindings, and trim-safe attribute plumbing on the tool registration. Combined with --self-contained, you get a single-file executable that starts in tens of milliseconds, which matters for stdio servers because the agent forks them on every session.

A minimal stdio scaffold looks like this:

// Program.cs -- generated by dotnet new mcpserver --transport stdio
using Microsoft.Extensions.Hosting;
using ModelContextProtocol.Server;
using System.ComponentModel;

var builder = Host.CreateApplicationBuilder(args);

builder.Logging.AddConsole(o =>
{
    // stderr only -- stdout is the protocol channel
    o.LogToStandardErrorThreshold = LogLevel.Trace;
});

builder.Services
    .AddMcpServer()
    .WithStdioServerTransport()
    .WithToolsFromAssembly();

await builder.Build().RunAsync();

[McpServerToolType]
public static class EchoTool
{
    [McpServerTool, Description("Echo the input back.")]
    public static string Echo(string message) => $"hello {message}";
}

The stderr-only logging is baked in, which is the single biggest gotcha first-timers hit: any stray Console.WriteLine on stdout corrupts the JSON-RPC stream and the agent reports a protocol error with no useful detail.

Picking it up alongside an existing project

If you already have an MCP server scaffolded the old way (see the deeper walkthrough in How to Build a Custom MCP Server in C# on .NET 11), there is no migration needed. The bundled template generates the same ModelContextProtocol package references the old one did. The change is purely about how new projects start.

The thing worth doing today: pin global.json to 11.0.100-preview.4, drop the dotnet new install Microsoft.McpServer.ProjectTemplates line from your team setup docs and your devcontainer, and watch one onboarding-day Slack question disappear.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Back