.NET 11

.NET 11 baut Ihnen einen MCP-Server mit einem Befehl. Absichern müssen Sie ihn weiterhin selbst.

Seit dem 10. November 2026 gehört das MCP-Server-Template zum .NET SDK. Damit stellen Sie Ihre Geschäftslogik schnell einem KI-Agenten zur Verfügung, und vergessen ebenso schnell, dass dieser Agent ein Client ist, dem Sie nicht vertrauen können.

01
MCP Client + LLM
Nicht vertrauenswürdig. Das Modell wählt Tool und Argumente.
↓
02
ASP.NET Core
Prüft Token, Audience und Scope.
↓
03
MCP Tool
Handelt als angemeldeter Benutzer, nicht mehr.
Das Template

dotnet new mcpserver, ohne Zusatzinstallation

.NET 11 ist seit dem 10. November 2026 verfügbar, ein Standard-Term-Support-Release mit zwei Jahren Support. Neben Union Types in C# 15 und einer schnelleren CLI bringt es eine kleine Änderung mit grosser Wirkung: Das Template mcpserver ist jetzt Teil des SDK. Bis .NET 10 mussten Sie zuerst Microsoft.McpServer.ProjectTemplates installieren.

Das Template baut auf dem offiziellen MCP C# SDK auf und erzeugt einen lauffähigen Server mit einem Beispiel-Tool. Standardmässig entsteht eine Konsolen-App mit stdio, dem Transport, den lokale Clients wie VS Code, Visual Studio oder Claude Code als Kindprozess starten.

Terminal
dotnet new mcpserver -o OrdersMcp
dotnet new mcpserver -o OrdersMcp --transport remote
Option Wirkung
-t local Standard. Konsolen-App mit stdio-Transport, als .NET Tool mit PackageType McpServer für NuGet verpackt.
-t remote ASP.NET Core App mit HTTP-Transport über MapMcp(), standardmässig zustandslos.
--aot Bereitet den Server auf die Veröffentlichung mit Native AOT vor.
--self-contained Standardmässig aktiv. Liefert die Runtime mit, der Client-Rechner braucht kein installiertes .NET.
-f net10.0 Zielframework, standardmässig net11.0, net10.0 für das LTS-Release.

Ein Tool ist eine gewöhnliche Methode. [McpServerTool] stellt sie als get_random_number bereit, und die [Description]-Texte liest das Modell, um zu entscheiden, wann und wie es sie aufruft. Behandeln Sie sie wie API-Dokumentation für einen sehr wörtlichen Leser. Ein Detail: Das Template referenziert ModelContextProtocol 2.1.0, neuere SDK-Versionen sind bereits auf NuGet.

Tools/RandomNumberTools.cs
internal class RandomNumberTools
{
    [McpServerTool]
    [Description("Generates a random number between the specified minimum and maximum values.")]
    public int GetRandomNumber(
        [Description("Minimum value (inclusive)")] int min = 0,
        [Description("Maximum value (exclusive)")] int max = 100)
    {
        return Random.Shared.Next(min, max);
    }
}
Bausteine

Wo MCP im .NET AI-Stack hingehört

MCP ist einer von vier Bausteinen, die Microsoft für KI in .NET nennt. Jeder löst sein eigenes Problem, und sie lassen sich kombinieren.

Microsoft.Extensions.AI

IChatClient und IEmbeddingGenerator als eine Abstraktion über alle Modellanbieter, mit DI, Caching, Logging und OpenTelemetry als Middleware.

Microsoft.Extensions.VectorData

Embeddings speichern und semantisch suchen hinter einer Abstraktion, für RAG über Ihre eigenen Daten.

Microsoft Agent Framework

Agenten mit Tools, Gesprächsverlauf und mehrstufigen Workflows. Agenten können MCP-Tools direkt nutzen.

Model Context Protocol

Das offene Protokoll zwischen einem KI-Client und Ihrer Software. Ihr Server stellt Tools, Ressourcen und Prompts bereit, jeder MCP-fähige Agent kann sie nutzen.

Vertrauen

Ein MCP-Client ist ein Client wie jeder andere

Ein MCP-Server ist eine API. Der einzige Unterschied zu einer REST-API ist, wer aufruft: nicht Ihr eigenes Frontend, sondern ein Sprachmodell, das Text aus E-Mails, Tickets, Webseiten oder Dokumenten liest und entscheidet, welches Tool es mit welchen Argumenten aufruft. Ein einziger präparierter Satz in einem solchen Text (Prompt Injection) genügt, damit es etwas aufruft, das niemand wollte.

Deshalb gilt dieselbe Regel wie für jeden Browser: Der Server entscheidet, was erlaubt ist, nie der Client. Und das Remote-Template startet offen, ganz ohne Authentifizierung. Wer den Endpunkt erreicht, kann jedes Tool aufrufen.

Das Modell wählt die Argumente

Ein Parameter customerId ist eine Einladung. Leiten Sie Identität und Mandant aus dem geprüften Token ab, nicht aus dem, was das Modell übergibt.

Versteckt ist nicht verboten

tools/list zu filtern ist bequem, aber ein Client kann jeden Tool-Namen direkt aufrufen. Die Prüfung muss beim Aufruf auf dem Server passieren.

Der Server handelt als Benutzer

Ein Tool darf nie mehr tun, als der angemeldete Benutzer in Ihrer normalen Anwendung könnte. Ein Service-Account mit Vollzugriff macht aus jeder Prompt Injection ein Datenleck.

Authentifizierung

Das Remote-Template mit OAuth absichern

Die MCP-Spezifikation setzt für HTTP-Server auf OAuth 2.1. Ihr Server ist die geschützte Ressource, ein bestehender Identity Provider wie Entra ID, Keycloak oder Auth0 stellt die Tokens aus. ModelContextProtocol.AspNetCore liefert die fehlenden Teile: AddMcp() veröffentlicht die Protected Resource Metadata (RFC 9728), damit Clients das Login finden, AddAuthorizationFilters() lässt [Authorize] auf einzelnen Tools wirken.

Program.cs
using Microsoft.AspNetCore.Authentication.JwtBearer;
using ModelContextProtocol.AspNetCore.Authentication;
using ModelContextProtocol.Authentication;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = McpAuthenticationDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        options.Authority = "https://login.example.com";
        options.Audience = "https://mcp.example.com";
    })
    .AddMcp(options =>
    {
        options.ResourceMetadata = new ProtectedResourceMetadata
        {
            AuthorizationServers = ["https://login.example.com"],
            ScopesSupported = ["orders.read", "orders.write"]
        };
    });

builder.Services.AddAuthorization(options =>
    options.AddPolicy("orders.write", policy => policy.RequireClaim("scope", "orders.write")));

builder.Services
    .AddMcpServer()
    .WithHttpTransport(options => options.Stateless = true)
    .AddAuthorizationFilters()
    .WithTools<OrderTools>();

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapMcp().RequireAuthorization();
app.Run();

Den Rest erledigt gewöhnliches ASP.NET Core. JWT Bearer prüft Signatur, Issuer und Audience, RequireAuthorization() sperrt den ganzen Endpunkt, und eine Policy pro Scope schützt einzelne Tools. Das Tool selbst nimmt einen ClaimsPrincipal als Parameter und kennt den Benutzer aus dem Token, nicht vom Modell.

Tools/OrderTools.cs
internal class OrderTools
{
    [McpServerTool, Description("Lists the open orders of the signed-in customer.")]
    public string[] GetOpenOrders(ClaimsPrincipal user) =>
        [$"orders for {user.FindFirstValue(ClaimTypes.NameIdentifier)}"];

    [McpServerTool, Description("Cancels one order of the signed-in customer.")]
    [Authorize(Policy = "orders.write")]
    public string CancelOrder(ClaimsPrincipal user, [Description("Order number")] string orderId) =>
        $"cancel {orderId} for {user.FindFirstValue(ClaimTypes.NameIdentifier)}";
}

Was auf der Leitung passiert

  • Ohne Token antwortet der Server mit 401 und einem WWW-Authenticate-Header, der auf die Metadaten zeigt. So weiss ein MCP-Client, wo er sich anmelden muss.
  • /.well-known/oauth-protected-resource nennt den Authorization Server und die unterstützten Scopes.
  • Mit Scope orders.read liefert tools/list nur get_open_orders. Kommt orders.write dazu, erscheint auch cancel_order.
  • Ruft der Client cancel_order trotzdem auf, lehnt der Server ab. Der Filter in der Liste ist Komfort, die Prüfung beim Aufruf ist der Schutz.
  • Ein Token, das derselbe Identity Provider für eine andere Anwendung ausgestellt hat, bekommt 401, weil der Server nur seine eigene Audience akzeptiert. In unserem ersten Testlauf war die Audience falsch konfiguriert, und das fremde Token kam ohne Weiteres durch.
  • Das Gegenbeispiel: ein Tool mit Parameter customerId. Angemeldet als alice liefert der Aufruf mit bob die Bestellungen von bob. Die Authentifizierung war korrekt, das Tool nicht.
Antworten des Beispiel-Servers
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="http://localhost:6182/.well-known/oauth-protected-resource/"

GET /.well-known/oauth-protected-resource
{"resource":"http://localhost:6182","authorization_servers":["https://login.example.com"],
 "bearer_methods_supported":["header"],"scopes_supported":["orders.read","orders.write"]}

tools/call cancel_order (scope orders.read)
{"error":{"code":-32600,"message":"Access forbidden: This tool requires authorization."}}

tools/list (token for https://other-app.example.com)
HTTP/1.1 401 Unauthorized

tools/call get_orders_for {"customerId":"bob"} (signed in as alice)
{"result":{"content":[{"type":"text","text":"[\"orders for bob\"]"}]}}

Getestet am 12. November 2026 mit .NET SDK 11.0.100, dem ModelContextProtocol.AspNetCore 2.1.0 aus dem Template und Tokens aus dotnet user-jwts.

Checkliste

Bevor Ihr MCP-Server in Produktion geht

Audience prüfen

Akzeptieren Sie nur Tokens, die für diesen Server ausgestellt wurden. Ohne Prüfung der Audience funktioniert auch ein Token für eine andere Anwendung desselben Identity Providers auf Ihrem MCP-Server.

Kein Token-Passthrough

Die MCP-Spezifikation verbietet, das Token des Clients an nachgelagerte APIs weiterzureichen. Holen Sie für diese Aufrufe ein eigenes Token, zum Beispiel per On-Behalf-Of, damit jedes System seine eigenen Berechtigungen prüft.

Kleine Scopes pro Tool

Lesen und Schreiben gehören in getrennte Scopes. Clients fordern dann nur an, was die Aufgabe braucht, und ein gestohlenes Token richtet weniger Schaden an.

stdio ist keine Sandbox

Ein lokaler Server läuft mit den Rechten des Benutzers, der ihn startet, und für stdio definiert die Spezifikation keinen OAuth-Ablauf. Übergeben Sie Secrets über Umgebungsvariablen, nie als Tool-Argument, und geben Sie dem Server nur den Zugriff, den er braucht.

Bestätigung für Unumkehrbares

Stornieren, löschen, bezahlen: Lassen Sie einen Menschen bestätigen, bevor das Tool handelt, im Client oder per Elicitation vom Server, die den zustandsbehafteten HTTP-Modus braucht. Das Modell darf vorschlagen, entscheiden soll es nicht allein.

Jeden Tool-Aufruf protokollieren

Wer hat welches Tool mit welchen Argumenten aufgerufen, und was kam zurück? Logging und OpenTelemetry in ASP.NET Core machen das nachvollziehbar, ohne zusätzliche Infrastruktur.

FAQ

Häufige Fragen zu MCP-Servern in .NET 11

Ist das MCP-Server-Template im .NET 11 SDK enthalten?

Ja. Seit .NET 11, erschienen am 10. November 2026, funktioniert dotnet new mcpserver ohne zusätzliche Installation. Bis .NET 10 kam das Template aus dem separaten Paket Microsoft.McpServer.ProjectTemplates.

Enthält das .NET MCP-Server-Template eine Authentifizierung?

Nein. Das Remote-Template mit HTTP-Transport startet ohne Authentifizierung, wer den Endpunkt erreicht, kann jedes Tool aufrufen. Sie ergänzen sie mit ASP.NET Core Authentication, JWT Bearer und AddMcp() aus ModelContextProtocol.AspNetCore.

Wie beschränke ich ein einzelnes MCP-Tool in .NET auf bestimmte Benutzer?

Rufen Sie AddAuthorizationFilters() auf dem MCP-Server-Builder auf und setzen Sie [Authorize] mit einer Policy oder Rolle auf die Tool-Methode oder -Klasse. Benutzer ohne Berechtigung sehen das Tool nicht in tools/list, und ein direkter Aufruf wird abgelehnt.

Warum kann ein MCP-Server seinem Client nicht vertrauen?

Der Client wird von einem Sprachmodell gesteuert, das nicht vertrauenswürdigen Text liest und Tools und Argumente selbst wählt. Eine Prompt Injection kann es dazu bringen, jedes Tool mit jedem Wert aufzurufen, deshalb muss der Server Identität und Berechtigung bei jedem Aufruf prüfen, genau wie bei einem Browser.

Brauchen stdio MCP-Server OAuth?

Nein. Der Autorisierungsteil der MCP-Spezifikation gilt für HTTP-Transporte. Ein stdio-Server läuft lokal mit den Rechten des Benutzers, der ihn startet, und liest seine Zugangsdaten aus der Umgebung.

Darf ein MCP-Server das Access Token des Clients an andere APIs weiterreichen?

Nein. Die MCP-Spezifikation verbietet Token-Passthrough. Der Server akzeptiert nur Tokens, die für ihn ausgestellt wurden, und holt sich für nachgelagerte Aufrufe ein eigenes Token, zum Beispiel mit dem On-Behalf-Of-Flow.

Ihre Software

Ihre .NET-Software sicher agentenfähig machen

Wir bauen MCP-Server für bestehende .NET-Anwendungen, angebunden an Ihren Identity Provider und mit genau den Berechtigungen, die Ihre Benutzer bereits haben. Kein Service-Account mit Vollzugriff, kein Tool-Aufruf, den niemand nachvollziehen kann.

Mehr zu KI-Agenten für Ihre Software

Kontakt

Erzählen Sie uns, was Sie vorhaben.

Sie sprechen direkt mit den Leuten, die später auch Ihren Code schreiben.

  1. Sie melden sich: Wir geben unser Bestes, innert 24 Stunden zu antworten.
  2. Wir lernen uns kennen: 30 Minuten. Sie erzählen, wir fragen nach. Kein Pitch.
  3. Wir entscheiden gemeinsam: Wie es weitergeht, oder ehrlich, dass wir nicht passen.
0 / 2000

Ein paar Sätze reichen. Was hält Sie heute auf, gibt es einen Termin?

Wir nutzen Ihre Angaben nur, um Ihnen zu antworten.

Lieber direkt sprechen? 30 Minuten per Google Meet mit Steven Giesel.

Termin wählen
Oder per E-Mail an contact@bitspire.ch