dotnet new mcpserver теперь поставляется в SDK .NET 11 Preview 4
.NET 11 Preview 4 включает шаблон проекта mcpserver прямо в SDK. Без отдельной установки Microsoft.McpServer.ProjectTemplates, без танцев с preview-фидами. Выбираете транспорт stdio или HTTP, включаете Native AOT, и dotnet new mcpserver -o MyServer -- это вся настройка.
В release notes .NET 11 Preview 4 есть маленькая, но опорная строка для всех, кто поставляет серверы Model Context Protocol на C#: шаблон проекта mcpserver, раньше доступный только через установку Microsoft.McpServer.ProjectTemplates, теперь поставляется как встроенный шаблон в .NET SDK. dotnet new list находит его без дополнительной установки, а его servicing едет вместе со стеком ASP.NET Core, а не отдельным NuGet-пакетом.
Что меняется в SDK Preview 4
Вплоть до .NET 11 Preview 3 рецепт нового MCP-сервера был в два шага:
# Preview 3 and earlier
dotnet new install Microsoft.McpServer.ProjectTemplates
dotnet new mcpserver -o InventoryMcp
На чистом CI-образе или при первом checkout коллеги шаг dotnet new install тихо ломался: он тянул из NuGet, имел собственную каденцию, а шаблон жил в профиле пользователя, который не переживает свежий devcontainer.
С Preview 4 (11.0.100-preview.4) шаг один исчезает:
dotnet new mcpserver -o InventoryMcp
cd InventoryMcp
dotnet run
Шаблон версионируется вместе с релизом SDK, поэтому пин в global.json на 11.0.100-preview.4 фиксирует и шаблон.
Что вы получаете из коробки
dotnet new mcpserver --help показывает ручки, которые поддерживает шаблон. Две самые важные:
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.
Здесь живут два настоящих выбора:
--transport stdio(по умолчанию) даёт консольный хост, говорящий по протоколу через stdin/stdout. Это то, что запускают Claude Code, Claude Desktop и VS Code, когда форкают MCP-потомка изmcp.json. Правильный ответ, когда агент на той же машине.--transport httpдаёт хост ASP.NET Core с замапленным транспортом Streamable HTTP. Берите его, когда сервер живёт за ingress и его делят несколько агентов.
Ключ --aot сразу обвязывает Native AOT publish: PublishAot=true в .csproj, AOT-совместимые source generators для биндингов протокола и trim-safe атрибутную обвязку в регистрации инструментов. В сочетании с --self-contained вы получаете single-file исполняемый файл, который стартует за десятки миллисекунд, что важно для stdio-серверов, потому что агент форкает их в каждой сессии.
Минимальный stdio-каркас выглядит так:
// 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}";
}
Логирование только в stderr включено из коробки, и это самая большая ловушка для новичков: любой случайный Console.WriteLine в stdout портит поток JSON-RPC, а агент сообщает об ошибке протокола без полезных деталей.
Как это вписывается в существующий проект
Если у вас уже есть MCP-сервер, собранный по старому (см. более глубокий разбор в Как собрать свой MCP-сервер на C# и .NET 11), миграция не нужна. Встроенный шаблон генерирует те же ссылки на пакет ModelContextProtocol, что и старый. Изменение касается только того, как стартуют новые проекты.
Что стоит сделать сегодня: запинить global.json на 11.0.100-preview.4, убрать строку dotnet new install Microsoft.McpServer.ProjectTemplates из командных setup-документов и devcontainer, и посмотреть, как из Slack исчезает один вопрос дня онбординга.
Comments
Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.