Phillip Pham | 9 Min. Lesezeit | 04.08.2026
TL;DR
FastMCP Entra ID heißt: Du hostest einen eigenen MCP-Server selbst und lässt Microsoft Entra ID über Gruppen-Mitgliedschaft entscheiden, welche Tools ein Nutzer aufrufen darf. Der AzureProvider erledigt den OAuth-Flow, der groups-Claim im Token steuert das Tool-Gating. Ergebnis: kein Shared-Key, saubere Rechte pro Abteilung, Audit-Trail aus Entra.
Warum ein interner MCP-Server ohne RBAC gefährlich ist
Die kurze Antwort: Weil ein MCP-Server Tools ausführt, nicht nur Text liefert. Ein Tool wie run_sql, delete_ticket oder read_hr_document ist kein Chat, sondern eine Aktion auf einem Produktivsystem. Wer den Server über einen einzelnen Bearer-Key absichert, gibt jedem Client, der den Key hat, jedes Tool. Das ist der Punkt, an dem zwei unserer Kunden vor genau dieser Frage standen.
Bei einem MCP-Server, der über einen statischen Key läuft, kann niemand nachträglich sagen, welcher Mensch welches Tool ausgelöst hat. Für DORA, NIS-2 oder eine interne Revision ist das ein Totalausfall. Der Server weiß, dass ein Aufruf kam, aber nicht von wem.
Entra ID löst beides in einem Schritt: Authentifizierung (wer ist das?) und Autorisierung (was darf der?). Die Gruppen, die du in Entra sowieso pflegst, werden zur Zugriffsregel für deine Tools. Kein zweites Rechtesystem, keine YAML-Datei mit Nutzerlisten, die niemand pflegt.
FastMCP Entra ID: so hängt die Gruppen-RBAC am Server
FastMCP ist mit rund 27.100 GitHub-Sternen (Abruf 04.08.2026) das De-facto-Framework für MCP-Server in Python. Version 3.4.5 (Stand Juli 2026) ist stabil, FastMCP 4.0 läuft seit dem 28.07.2026 als Beta (4.0.0b1). Ab Version 3.0.0 unterstützt der AzureProvider auch den On-Behalf-Of-Flow, mit dem der Server im Namen des Nutzers weitere APIs anspricht.
Der AzureProvider sitzt direkt am FastMCP-Objekt. Er übernimmt den kompletten OAuth-Handshake gegen deinen Entra-Tenant. Weil Azure keine Dynamic Client Registration kennt, nutzt FastMCP das OAuth-Proxy-Muster: Der Server tauscht das Azure-Token gegen ein eigenes JWT und hält das Azure-Token serverseitig verschlüsselt.
from fastmcp import FastMCP
from fastmcp.server.auth.providers.azure import AzureProvider
auth_provider = AzureProvider(
client_id="835f09b6-0f0f-40cc-85cb-f32c5829a149",
client_secret="<aus Key Vault, nie im Code>",
tenant_id="08541b6e-646d-43de-a0eb-834e6713d6d5", # nicht "common"
base_url="https://mcp.internal.pexon.de",
required_scopes=["mcp.access"],
)
mcp = FastMCP(name="Internal Tool Server", auth=auth_provider)
Ab hier ist jeder Zugriff auf den Server authentifiziert. Ein anonymer Aufruf wird abgewiesen, bevor überhaupt ein Tool sichtbar wird. Das ist die halbe Miete, aber noch keine RBAC: Jeder eingeloggte Nutzer sieht bis hierher weiterhin alle Tools.
Gruppen-Claim aktivieren und Tools gaten
Damit die Gruppen im Token landen, musst du sie in der App-Registrierung explizit anschalten. In Entra unter Token configuration einen groups claim hinzufügen (Typ „Security groups“). Danach trägt jedes Access-Token einen groups-Array mit den Objekt-IDs der Gruppen, in denen der Nutzer Mitglied ist.
Eine Warnung aus der Praxis: Ab etwa 200 Gruppen pro Nutzer setzt Entra ein Overage-Flag statt der vollen Liste. Dann musst du die Mitgliedschaft über Microsoft Graph nachladen. Für die meisten internen Server mit einer Handvoll relevanter Gruppen ist das kein Thema, aber plane es ein, bevor die erste Führungskraft mit 300 Gruppen im Token auftaucht.
Im Server liest du den Claim über die get_access_token()-Dependency und gatest jedes Tool gegen die geforderte Gruppe:
from fastmcp.server.dependencies import get_access_token
from fastmcp.exceptions import ToolError
# Objekt-IDs aus Entra, hier statt Magic-Strings sauber benannt
GROUP_SQL_ADMINS = "a1b2c3d4-1111-2222-3333-444455556666"
GROUP_HR_READERS = "f6e5d4c3-9999-8888-7777-666655554444"
def require_group(group_id: str) -> None:
claims = get_access_token().claims
if group_id not in claims.get("groups", []):
raise ToolError("Kein Zugriff: erforderliche Entra-Gruppe fehlt.")
@mcp.tool
async def run_sql(query: str) -> list[dict]:
"""Fuehrt eine Read-Query gegen das DWH aus."""
require_group(GROUP_SQL_ADMINS)
return await execute_readonly(query)
@mcp.tool
async def read_hr_document(doc_id: str) -> str:
"""Liest ein HR-Dokument."""
require_group(GROUP_HR_READERS)
return await hr_store.get(doc_id)
Unsere Empfehlung: Halte die Gruppen-IDs in einer zentralen Konfiguration, nicht verteilt über den Code. Sonst suchst du beim nächsten Umbau der Entra-Struktur an zwanzig Stellen. Für feinere Fälle lässt sich derselbe require_group-Check in eine FastMCP-Middleware ziehen, die vor jedem Tool-Aufruf greift und zusätzlich den Nutzer plus die Gruppe ins Audit-Log schreibt.
Die Gruppe-zu-Tool-Zuordnung gehört dokumentiert. Eine schlichte Tabelle reicht und ist gleichzeitig die Vorlage für das Berechtigungskonzept, das die Revision sehen will:
Self-hosten: wo der interne MCP-Server läuft
MCP-Server intern betreiben heißt nicht zwingend on-premise. Der Server ist ein normaler ASGI-Prozess und läuft überall, wo Python läuft: Azure Container Apps, ein AKS-Pod, eine VM im eigenen Rechenzentrum. Entscheidend ist nur, dass die base_url im Code exakt zur Redirect-URI in der App-Registrierung passt, sonst bricht der OAuth-Callback.
Für einen ersten produktiven Betrieb reicht ein einzelner Container hinter einem internen Reverse-Proxy, der TLS terminiert. Als MCP-Client hängt dann zum Beispiel Claude (claude-opus-4-8) oder ein eigener LangGraph-Agent daran. Der Client bekommt beim ersten Zugriff den Entra-Login, danach übernimmt FastMCP das Token-Refresh automatisch.
Ein Punkt, den wir bei Kunden immer wieder korrigieren: Der client_secret gehört in Azure Key Vault, nicht in eine .env-Datei im Repo. Und jwt_signing_key sowie ein persistenter, verschlüsselter Token-Store sind ab Version 2.13.0 kein Nice-to-have, sondern Voraussetzung dafür, dass nach einem Neustart nicht jeder Nutzer erneut den Login-Flow durchlaufen muss.
Für komplexere Server lohnt ein Blick darauf, wie sich mehrere FastMCP-Server komponieren lassen und Resources statt Tools nutzen. Und wer den Server-Betrieb in eine größere Architektur einordnen will, findet den Rahmen in unserer MCP-Orchestrierung für Agenten.
MCP Registry: braucht der interne Server einen Eintrag?
Kurz: nein, nicht die öffentliche. Die offizielle MCP Registry (registry.modelcontextprotocol.io) ist seit dem 08.09.2025 in der Preview und weiterhin nicht GA, getragen von Anthropic, GitHub und Microsoft. Sie ist ein Katalog für öffentlich erreichbare Server. Ein interner Tool-Server hat dort nichts zu suchen.
Was intern Sinn ergibt, ist eine eigene Subregistry: ein privater Katalog, über den Teams sehen, welche MCP-Server es im Haus gibt, wer sie betreibt und welche Gruppe Zugriff hat. Das ist Discovery plus Governance in einem und wächst genau in dem Moment zum Thema, in dem der zweite und dritte Server dazukommen. Wichtig zum Einordnen: Die aktuelle MCP-Spezifikation liegt seit dem 28.07.2026 als Release Candidate vor, die Auth-Grundlagen (OAuth, Resource Indicators) sind darin stabil. Du baust also nicht auf Sand.
Häufig gestellte Fragen
Was kostet ein interner MCP-Server mit Entra-RBAC?
Die Software ist Open Source, FastMCP kostet nichts. Der Aufwand steckt in App-Registrierung, Gruppen-Konzept und Betrieb. Für einen ersten produktiven Server mit drei bis fünf Tools und sauberem RBAC rechnen wir im Pilot mit rund zwei bis vier Wochen, je nachdem wie geordnet die Entra-Gruppen schon sind.
Reicht ein Bearer-Token statt des vollen OAuth-Flows?
Für einen internen Prototyp ja, für Produktion nein. Ein statischer Token gibt jedem, der ihn hat, alle Tools und hinterlässt keinen Nutzerbezug im Log. Sobald ein Tool schreibend auf ein Produktivsystem zugreift, brauchst du den Nutzerbezug aus Entra, sonst scheitert jede Revision.
FastMCP AzureProvider oder AzureJWTVerifier, was ist der Unterschied?
Der AzureProvider führt den kompletten interaktiven OAuth-Flow inklusive Login. Der AzureJWTVerifier prüft nur bereits ausgestellte Tokens, sinnvoll wenn ein vorgelagertes Gateway den Login schon erledigt hat. Für einen selbst gehosteten Server mit direkten Clients ist der AzureProvider der Standardweg.
Was passiert bei mehr als 200 Gruppen pro Nutzer?
Entra setzt dann ein Overage-Indikator ins Token statt der vollen Gruppenliste. Dein Server muss die Mitgliedschaft in dem Fall über Microsoft Graph nachladen. Plane das ein, wenn Nutzer in vielen Gruppen sind, sonst schlägt die RBAC-Prüfung stumm fehl.
Läuft das auch on-premise ohne Azure-Hosting?
Ja. Der Server läuft in jedem Container oder auf jeder VM im eigenen Rechenzentrum. Nur der Identity-Layer (Entra ID) liegt in der Microsoft-Cloud. Wer auch die Identität souverän halten muss, kann den AzureJWTVerifier gegen einen eigenen OIDC-Provider tauschen, das ist aber ein anderes Projekt.
Nächster Schritt
Wenn du gerade einen internen MCP-Server planst und beim Rechte-Layer unsicher bist: Wir haben das Muster mehrfach produktiv gebaut und schauen mit dir in einem kurzen Call auf deinen konkreten Fall.
Verwandte Themen
→Open WebUI per Entra-SSO an die interne KI anbinden
→Agent-Zugriffe generell über Entra-Gruppen absichern



