Tutorial: Wer bin ich? (Tutorial: Who am I?)
Dieses Tutorial führt dich durch den Prozess der Einrichtung von MCP Auth, um Benutzer zu authentifizieren und deren Identitätsinformationen vom Autorisierungsserver abzurufen.
Nach Abschluss dieses Tutorials hast du:
- ✅ Ein grundlegendes Verständnis davon, wie du MCP Auth zur Authentifizierung von Benutzern verwendest.
- ✅ Einen MCP-Server, der ein Tool zum Abrufen von Benutzeridentitätsinformationen bereitstellt.
Überblick
Das Tutorial umfasst die folgenden Komponenten:
- MCP-Server: Ein einfacher MCP-Server, der die offiziellen MCP SDKs verwendet, um Anfragen zu verarbeiten.
- MCP Inspector: Ein visuelles Testwerkzeug für MCP-Server. Es fungiert auch als OAuth / OIDC-Client, um den Autorisierungsfluss zu starten und Zugangstokens abzurufen.
- Autorisierungsserver: Ein OAuth 2.1- oder OpenID Connect-Anbieter, der Benutzeridentitäten verwaltet und Zugangstokens ausstellt.
Hier ist ein Überblicksdiagramm der Interaktion zwischen diesen Komponenten:
Deinen Autorisierungsserver verstehen
Benutzeridentitätsinformationen abrufen
Um dieses Tutorial abzuschließen, sollte dein Autorisierungsserver eine API zum Abrufen von Benutzeridentitätsinformationen bereitstellen:
- Logto
- Keycloak
- OIDC
- OAuth 2
Logto ist ein OpenID Connect-Anbieter, der den Standard-userinfo-Endpunkt unterstützt, um Benutzeridentitätsinformationen abzurufen.
Um ein Zugangstoken zu erhalten, das für den Zugriff auf den userinfo-Endpunkt verwendet werden kann, sind mindestens zwei Berechtigungen (scopes
) erforderlich: openid
und profile
. Du kannst weiterlesen, da wir die Berechtigungskonfiguration später behandeln.
Keycloak ist eine Open-Source-Lösung für Identitäts- und Zugriffsmanagement, die mehrere Protokolle unterstützt, darunter OpenID Connect (OIDC). Als OIDC-Anbieter implementiert es den Standard-userinfo-Endpunkt zum Abrufen von Benutzeridentitätsinformationen.
Um ein Zugangstoken zu erhalten, das für den Zugriff auf den userinfo-Endpunkt verwendet werden kann, sind mindestens zwei Berechtigungen (scopes
) erforderlich: openid
und profile
. Du kannst weiterlesen, da wir die Berechtigungskonfiguration später behandeln.
Die meisten OpenID Connect-Anbieter unterstützen den userinfo-Endpunkt zum Abrufen von Benutzeridentitätsinformationen.
Überprüfe die Dokumentation deines Anbieters, um zu sehen, ob dieser Endpunkt unterstützt wird. Wenn dein Anbieter OpenID Connect Discovery unterstützt, kannst du auch prüfen, ob der userinfo_endpoint
im Discovery-Dokument (Antwort vom .well-known/openid-configuration
-Endpunkt) enthalten ist.
Um ein Zugangstoken zu erhalten, das für den Zugriff auf den userinfo-Endpunkt verwendet werden kann, sind mindestens zwei Berechtigungen (scopes
) erforderlich: openid
und profile
. Überprüfe die Dokumentation deines Anbieters, um die Zuordnung der Berechtigungen zu Benutzeridentitätsansprüchen zu sehen.
Während OAuth 2.0 keine standardisierte Methode zum Abrufen von Benutzeridentitätsinformationen definiert, implementieren viele Anbieter eigene Endpunkte dafür. Überprüfe die Dokumentation deines Anbieters, um zu erfahren, wie du mit einem Zugangstoken Benutzeridentitätsinformationen abrufen kannst und welche Parameter erforderlich sind, um ein solches Zugangstoken beim Starten des Autorisierungsflusses zu erhalten.
Dynamische Client-Registrierung
Die dynamische Client-Registrierung ist für dieses Tutorial nicht erforderlich, kann aber nützlich sein, wenn du den MCP-Client-Registrierungsprozess mit deinem Autorisierungsserver automatisieren möchtest. Siehe Ist Dynamic Client Registration erforderlich? für weitere Details.
MCP-Server einrichten
Wir verwenden die offiziellen MCP SDKs, um einen MCP-Server mit einem whoami
-Tool zu erstellen, das Benutzeridentitätsinformationen vom Autorisierungsserver abruft.
Ein neues Projekt erstellen
- Python
- Node.js
mkdir mcp-server
cd mcp-server
uv init # Oder verwende `pipenv` oder `poetry`, um eine neue virtuelle Umgebung zu erstellen
Richte ein neues Node.js-Projekt ein:
mkdir mcp-server
cd mcp-server
npm init -y # Oder verwende `pnpm init`
npm pkg set type="module"
npm pkg set main="whoami.js"
npm pkg set scripts.start="node whoami.js"
MCP SDK und Abhängigkeiten installieren
- Python
- Node.js
pip install "mcp[cli]" starlette uvicorn
Oder ein anderes Paketverwaltungstool deiner Wahl, wie uv
oder poetry
.
npm install @modelcontextprotocol/sdk express
Oder ein anderes Paketverwaltungstool deiner Wahl, wie pnpm
oder yarn
.
MCP-Server erstellen
Erstellen wir zunächst einen MCP-Server, der ein whoami
-Tool implementiert.
- Python
- Node.js
Erstelle eine Datei namens whoami.py
und füge folgenden Code hinzu:
from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
from typing import Any
mcp = FastMCP("WhoAmI")
@mcp.tool()
def whoami() -> dict[str, Any]:
"""Ein Tool, das die Informationen des aktuellen Benutzers zurückgibt."""
return {"error": "Nicht authentifiziert"}
app = Starlette(
routes=[Mount('/', app=mcp.sse_app())]
)
Starte den Server mit:
uvicorn whoami:app --host 0.0.0.0 --port 3001
Da die aktuelle MCP Inspector-Implementierung keine Autorisierungsflüsse verarbeitet, verwenden wir den SSE-Ansatz, um den MCP-Server einzurichten. Wir aktualisieren den Code hier, sobald der MCP Inspector Autorisierungsflüsse unterstützt.
Du kannst auch pnpm
oder yarn
verwenden, wenn du möchtest.
Erstelle eine Datei namens whoami.js
und füge folgenden Code hinzu:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import express from 'express';
// Erstelle einen MCP-Server
const server = new McpServer({
name: 'WhoAmI',
version: '0.0.0',
});
// Füge dem Server ein Tool hinzu, das die Informationen des aktuellen Benutzers zurückgibt
server.tool('whoami', async () => {
return {
content: [{ type: 'text', text: JSON.stringify({ error: 'Nicht authentifiziert' }) }],
};
});
// Nachfolgend der Boilerplate-Code aus der MCP SDK-Dokumentation
const PORT = 3001;
const app = express();
const transports = {};
app.get('/sse', async (_req, res) => {
const transport = new SSEServerTransport('/messages', res);
transports[transport.sessionId] = transport;
res.on('close', () => {
delete transports[transport.sessionId];
});
await server.connect(transport);
});
app.post('/messages', async (req, res) => {
const sessionId = String(req.query.sessionId);
const transport = transports[sessionId];
if (transport) {
await transport.handlePostMessage(req, res, req.body);
} else {
res.status(400).send('Kein Transport für sessionId gefunden');
}
});
app.listen(PORT);
Starte den Server mit:
npm start
MCP-Server inspizieren
MCP Inspector klonen und ausführen
Jetzt, da der MCP-Server läuft, können wir den MCP Inspector verwenden, um zu sehen, ob das whoami
-Tool verfügbar ist.
Aufgrund der aktuellen Implementierung haben wir den MCP Inspector geforkt, um ihn flexibler und skalierbarer für Authentifizierung und Autorisierung zu machen. Wir haben auch einen Pull Request an das Original-Repository eingereicht, um unsere Änderungen einzubringen.
Um den MCP Inspector auszuführen, kannst du folgenden Befehl verwenden (Node.js wird benötigt):
git clone https://github.com/mcp-auth/inspector.git
cd inspector
npm install
npm run dev
Öffne dann deinen Browser und navigiere zu http://localhost:6274/
(oder einer anderen im Terminal angezeigten URL), um auf den MCP Inspector zuzugreifen.
MCP Inspector mit dem MCP-Server verbinden
Bevor wir fortfahren, überprüfe folgende Konfiguration im MCP Inspector:
- Transporttyp: Auf
SSE
setzen. - URL: Auf die URL deines MCP-Servers setzen. In unserem Fall sollte das
http://localhost:3001/sse
sein.
Jetzt kannst du auf die Schaltfläche "Connect" klicken, um zu sehen, ob der MCP Inspector eine Verbindung zum MCP-Server herstellen kann. Wenn alles in Ordnung ist, solltest du den Status "Connected" im MCP Inspector sehen.
Checkpoint: Das whoami
-Tool ausführen
- Klicke im oberen Menü des MCP Inspectors auf den Tab "Tools".
- Klicke auf die Schaltfläche "List Tools".
- Du solltest das
whoami
-Tool auf der Seite sehen. Klicke darauf, um die Tool-Details zu öffnen. - Du solltest auf der rechten Seite die Schaltfläche "Run Tool" sehen. Klicke darauf, um das Tool auszuführen.
- Du solltest das Tool-Ergebnis mit der JSON-Antwort
{"error": "Nicht authentifiziert"}
sehen.
Integration mit deinem Autorisierungsserver
Um diesen Abschnitt abzuschließen, sind mehrere Überlegungen zu beachten:
Die Issuer-URL deines Autorisierungsservers
Dies ist normalerweise die Basis-URL deines Autorisierungsservers, z. B. https://auth.example.com
. Einige Anbieter haben einen Pfad wie https://example.logto.app/oidc
, daher solltest du die Dokumentation deines Anbieters prüfen.
Wie du die Metadaten des Autorisierungsservers abrufst
- Wenn dein Autorisierungsserver dem OAuth 2.0 Authorization Server Metadata oder OpenID Connect Discovery entspricht, kannst du die integrierten MCP Auth-Utilities verwenden, um die Metadaten automatisch abzurufen.
- Wenn dein Autorisierungsserver diese Standards nicht unterstützt, musst du die Metadaten-URL oder Endpunkte manuell in der MCP-Server-Konfiguration angeben. Prüfe die Dokumentation deines Anbieters für die spezifischen Endpunkte.
Wie du den MCP Inspector als Client in deinem Autorisierungsserver registrierst
- Wenn dein Autorisierungsserver Dynamic Client Registration unterstützt, kannst du diesen Schritt überspringen, da sich der MCP Inspector automatisch als Client registriert.
- Wenn dein Autorisierungsserver keine Dynamic Client Registration unterstützt, musst du den MCP Inspector manuell als Client in deinem Autorisierungsserver registrieren.
Wie du Benutzeridentitätsinformationen abrufst und wie du die Parameter der Autorisierungsanfrage konfigurierst
-
Für OpenID Connect-Anbieter: In der Regel musst du beim Starten des Autorisierungsflusses mindestens die Berechtigungen
openid
undprofile
anfordern. Dadurch wird sichergestellt, dass das vom Autorisierungsserver zurückgegebene Zugangstoken die erforderlichen Berechtigungen für den Zugriff auf den userinfo-Endpunkt enthält, um Benutzeridentitätsinformationen abzurufen.Hinweis: Einige Anbieter unterstützen den userinfo-Endpunkt möglicherweise nicht.
-
Für OAuth 2.0 / OAuth 2.1-Anbieter: Prüfe die Dokumentation deines Anbieters, um zu erfahren, wie du mit einem Zugangstoken Benutzeridentitätsinformationen abrufen kannst und welche Parameter erforderlich sind, um ein solches Zugangstoken beim Starten des Autorisierungsflusses zu erhalten.
Während jeder Anbieter eigene spezifische Anforderungen haben kann, führen dich die folgenden Schritte durch den Prozess der Integration des MCP Inspectors und MCP Servers mit anbieter-spezifischen Konfigurationen.
MCP Inspector als Client registrieren
- Logto
- Keycloak
- OIDC
- OAuth 2
Die Integration mit Logto ist unkompliziert, da es sich um einen OpenID Connect-Anbieter handelt, der den Standard-userinfo-Endpunkt unterstützt, um Benutzeridentitätsinformationen abzurufen.
Da Logto derzeit keine Dynamic Client Registration unterstützt, musst du den MCP Inspector manuell als Client in deinem Logto-Tenant registrieren:
- Öffne deinen MCP Inspector, klicke auf die Schaltfläche "OAuth Configuration". Kopiere den Redirect URL (auto-populated)-Wert, der etwa so aussehen sollte:
http://localhost:6274/oauth/callback
. - Melde dich bei der Logto Console (oder deiner selbst gehosteten Logto Console) an.
- Navigiere zum Tab "Applications", klicke auf "Create application". Klicke unten auf der Seite auf "Create app without framework".
- Fülle die Anwendungsdetails aus und klicke dann auf "Create application":
- Wähle einen Anwendungstyp: Wähle "Single-page application".
- Anwendungsname: Gib einen Namen für deine Anwendung ein, z. B. "MCP Inspector".
- Im Bereich "Settings / Redirect URIs" füge den zuvor kopierten Redirect URL (auto-populated)-Wert ein. Klicke dann unten auf "Save changes".
- Im oberen Bereich siehst du den Wert "App ID". Kopiere ihn.
- Gehe zurück zum MCP Inspector und füge den "App ID"-Wert im Bereich "OAuth Configuration" unter "Client ID" ein.
- Gib den Wert
{"scope": "openid profile email"}
im Feld "Auth Params" ein. Dadurch wird sichergestellt, dass das von Logto zurückgegebene Zugangstoken die erforderlichen Berechtigungen für den Zugriff auf den userinfo-Endpunkt enthält.
Keycloak ist eine Open-Source-Lösung für Identitäts- und Zugriffsmanagement, die das OpenID Connect-Protokoll unterstützt.
Obwohl Keycloak die dynamische Client-Registrierung unterstützt, unterstützt sein Client-Registrierungsendpunkt kein CORS, was die direkte Registrierung der meisten MCP-Clients verhindert. Daher müssen wir unseren Client manuell registrieren.
Obwohl Keycloak auf verschiedene Arten (Bare Metal, Kubernetes usw.) installiert werden kann, verwenden wir für dieses Tutorial Docker für eine schnelle und einfache Einrichtung.
Richte eine Keycloak-Instanz ein und konfiguriere sie wie folgt:
- Starte eine Keycloak-Instanz mit Docker gemäß der offiziellen Dokumentation:
docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.2.4 start-dev
-
Greife auf die Keycloak Admin Console (http://localhost:8080/admin) zu und melde dich mit diesen Zugangsdaten an:
- Benutzername:
admin
- Passwort:
admin
- Benutzername:
-
Erstelle ein neues Realm:
- Klicke oben links auf "Create Realm"
- Gib
mcp-realm
im Feld "Realm name" ein - Klicke auf "Create"
-
Erstelle einen Testbenutzer:
- Klicke im linken Menü auf "Users"
- Klicke auf "Create new user"
- Fülle die Benutzerdetails aus:
- Benutzername:
testuser
- Vorname und Nachname können beliebige Werte sein
- Benutzername:
- Klicke auf "Create"
- Setze im Tab "Credentials" ein Passwort und deaktiviere "Temporary"
-
Registriere den MCP Inspector als Client:
- Öffne deinen MCP Inspector, klicke auf die Schaltfläche "OAuth Configuration". Kopiere den Redirect URL (auto-populated)-Wert, der etwa so aussehen sollte:
http://localhost:6274/oauth/callback
. - Klicke in der Keycloak Admin Console im linken Menü auf "Clients"
- Klicke auf "Create client"
- Fülle die Client-Details aus:
- Client-Typ: Wähle "OpenID Connect"
- Client ID: Gib
mcp-inspector
ein - Klicke auf "Next"
- Auf der Seite "Capability config":
- Stelle sicher, dass "Standard flow" aktiviert ist
- Klicke auf "Next"
- Auf der Seite "Login settings":
- Füge die zuvor kopierte MCP Inspector Callback-URL in "Valid redirect URIs" ein
- Gib
http://localhost:6274
in "Web origins" ein - Klicke auf "Save"
- Kopiere die "Client ID" (das ist
mcp-inspector
)
- Öffne deinen MCP Inspector, klicke auf die Schaltfläche "OAuth Configuration". Kopiere den Redirect URL (auto-populated)-Wert, der etwa so aussehen sollte:
-
Zurück im MCP Inspector:
- Füge die kopierte Client ID in das Feld "Client ID" im Bereich "OAuth Configuration" ein
- Gib folgenden Wert im Feld "Auth Params" ein, um die erforderlichen Berechtigungen anzufordern:
{ "scope": "openid profile email" }
Dies ist eine allgemeine Anleitung zur Integration eines OpenID Connect-Anbieters. Prüfe die Dokumentation deines Anbieters für spezifische Details.
Wenn dein OpenID Connect-Anbieter die dynamische Client-Registrierung unterstützt, kannst du direkt zu Schritt 8 unten gehen, um den MCP Inspector zu konfigurieren; andernfalls musst du den MCP Inspector manuell als Client in deinem OpenID Connect-Anbieter registrieren:
- Öffne deinen MCP Inspector, klicke auf die Schaltfläche "OAuth Configuration". Kopiere den Redirect URL (auto-populated)-Wert, der etwa so aussehen sollte:
http://localhost:6274/oauth/callback
. - Melde dich bei der Konsole deines OpenID Connect-Anbieters an.
- Navigiere zum Bereich "Applications" oder "Clients" und erstelle eine neue Anwendung oder einen neuen Client.
- Wenn dein Anbieter einen Client-Typ verlangt, wähle "Single-page application" oder "Public client".
- Nach dem Erstellen der Anwendung musst du die Redirect URI konfigurieren. Füge den zuvor kopierten Redirect URL (auto-populated)-Wert ein.
- Finde die "Client ID" oder "Application ID" der neu erstellten Anwendung und kopiere sie.
- Gehe zurück zum MCP Inspector und füge die "Client ID" im Bereich "OAuth Configuration" unter "Client ID" ein.
- Für Standard-OpenID Connect-Anbieter kannst du folgenden Wert im Feld "Auth Params" eingeben, um die erforderlichen Berechtigungen für den Zugriff auf den userinfo-Endpunkt anzufordern:
{ "scope": "openid profile email" }
Dies ist eine allgemeine Anleitung zur Integration eines OAuth 2.0 / OAuth 2.1-Anbieters. Prüfe die Dokumentation deines Anbieters für spezifische Details.
Wenn dein OAuth 2.0 / OAuth 2.1-Anbieter die dynamische Client-Registrierung unterstützt, kannst du direkt zu Schritt 8 unten gehen, um den MCP Inspector zu konfigurieren; andernfalls musst du den MCP Inspector manuell als Client in deinem OAuth 2.0 / OAuth 2.1-Anbieter registrieren:
- Öffne deinen MCP Inspector, klicke auf die Schaltfläche "OAuth Configuration". Kopiere den Redirect URL (auto-populated)-Wert, der etwa so aussehen sollte:
http://localhost:6274/oauth/callback
. - Melde dich bei der Konsole deines OAuth 2.0 / OAuth 2.1-Anbieters an.
- Navigiere zum Bereich "Applications" oder "Clients" und erstelle eine neue Anwendung oder einen neuen Client.
- Wenn dein Anbieter einen Client-Typ verlangt, wähle "Single-page application" oder "Public client".
- Nach dem Erstellen der Anwendung musst du die Redirect URI konfigurieren. Füge den zuvor kopierten Redirect URL (auto-populated)-Wert ein.
- Finde die "Client ID" oder "Application ID" der neu erstellten Anwendung und kopiere sie.
- Gehe zurück zum MCP Inspector und füge die "Client ID" im Bereich "OAuth Configuration" unter "Client ID" ein.
- Lies die Dokumentation deines Anbieters, um zu erfahren, wie du Zugangstokens für Benutzeridentitätsinformationen abrufst. Möglicherweise musst du die erforderlichen Berechtigungen oder Parameter angeben, um das Zugangstoken zu erhalten. Wenn dein Anbieter z. B. die Berechtigung
profile
für den Zugriff auf Benutzeridentitätsinformationen verlangt, kannst du folgenden Wert im Feld "Auth Params" eingeben:
{ "scope": "profile" }
MCP Auth einrichten
In deinem MCP-Server-Projekt musst du das MCP Auth SDK installieren und es so konfigurieren, dass es die Metadaten deines Autorisierungsservers verwendet.
- Python
- Node.js
Installiere zunächst das mcpauth
-Paket:
pip install mcpauth
Oder ein anderes Paketverwaltungstool deiner Wahl, wie uv
oder poetry
.
Installiere zunächst das mcp-auth
-Paket:
npm install mcp-auth
MCP Auth benötigt die Metadaten des Autorisierungsservers, um initialisiert werden zu können. Je nach Anbieter:
- Logto
- Keycloak
- OIDC
- OAuth 2
Die Issuer-URL findest du auf der Anwendungsdetailseite in der Logto Console im Abschnitt "Endpoints & Credentials / Issuer endpoint". Sie sollte etwa so aussehen: https://my-project.logto.app/oidc
.
- Python
- Node.js
Aktualisiere die whoami.py
, um die MCP Auth-Konfiguration einzubinden:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Ersetze dies durch deinen Issuer-Endpunkt
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Aktualisiere die whoami.js
, um die MCP Auth-Konfiguration einzubinden:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Ersetze dies durch deinen Issuer-Endpunkt
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Nun müssen wir einen benutzerdefinierten Zugangstoken (Access token) Verifizierer erstellen, der die Benutzeridentitätsinformationen vom Autorisierungsserver mit dem vom MCP-Inspector bereitgestellten Zugangstoken abruft.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt mit den Benutzerinformationen zurückgegeben.
:param token: Das vom MCP-Inspector erhaltene Bearer-Token.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # Der Anbieter sollte den userinfo-Endpunkt unterstützen
if not endpoint:
raise ValueError(
"Userinfo-Endpunkt ist in den Auth-Server-Metadaten nicht konfiguriert."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # Standard Bearer-Token-Header
)
response.raise_for_status() # Fehler bei HTTP-Fehlern auslösen
json = response.json() # Die JSON-Antwort parsen
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' ist ein Standard-Anspruch (Claim) für das Subjekt (Benutzer-ID)
issuer=issuer, # Verwende den Aussteller (Issuer) aus den Metadaten
claims=json, # Alle Ansprüche (Claims) (JSON-Felder), die vom userinfo-Endpunkt zurückgegeben werden
)
# `AuthInfo` ist ein Pydantic-Modell, daher bedeuten Validierungsfehler meist, dass die Antwort nicht der erwarteten Struktur entspricht
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Andere Ausnahmen behandeln, die während der Anfrage auftreten können
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
* Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt mit den Benutzerinformationen zurückgegeben.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('Userinfo-Endpunkt ist in den Server-Metadaten nicht konfiguriert');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' ist ein Standard-Anspruch (Claim) für das Subjekt (Benutzer-ID)
clientId: '', // Client ID wird in diesem Beispiel nicht verwendet, kann aber gesetzt werden
scopes: [],
claims: userInfo,
};
};
Die Issuer-URL findest du in deiner Keycloak Admin Console. Navigiere in deinem 'mcp-realm' zum Abschnitt "Realm settings / Endpoints" und klicke auf den Link "OpenID Endpoint Configuration". Das Feld issuer
im JSON-Dokument enthält deine Issuer-URL, die etwa so aussehen sollte: http://localhost:8080/realms/mcp-realm
.
- Python
- Node.js
Aktualisiere die whoami.py
, um die MCP Auth-Konfiguration einzubinden:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Ersetze dies durch deinen Issuer-Endpunkt
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Aktualisiere die whoami.js
, um die MCP Auth-Konfiguration einzubinden:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Ersetze dies durch deinen Issuer-Endpunkt
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Nun müssen wir einen benutzerdefinierten Zugangstoken (Access token) Verifizierer erstellen, der die Benutzeridentitätsinformationen vom Autorisierungsserver mit dem vom MCP-Inspector bereitgestellten Zugangstoken abruft.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt mit den Benutzerinformationen zurückgegeben.
:param token: Das vom MCP-Inspector erhaltene Bearer-Token.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # Der Anbieter sollte den userinfo-Endpunkt unterstützen
if not endpoint:
raise ValueError(
"Userinfo-Endpunkt ist in den Auth-Server-Metadaten nicht konfiguriert."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # Standard Bearer-Token-Header
)
response.raise_for_status() # Fehler bei HTTP-Fehlern auslösen
json = response.json() # Die JSON-Antwort parsen
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' ist ein Standard-Anspruch (Claim) für das Subjekt (Benutzer-ID)
issuer=issuer, # Verwende den Aussteller (Issuer) aus den Metadaten
claims=json, # Alle Ansprüche (Claims) (JSON-Felder), die vom userinfo-Endpunkt zurückgegeben werden
)
# `AuthInfo` ist ein Pydantic-Modell, daher bedeuten Validierungsfehler meist, dass die Antwort nicht der erwarteten Struktur entspricht
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Andere Ausnahmen behandeln, die während der Anfrage auftreten können
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
* Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt mit den Benutzerinformationen zurückgegeben.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('Userinfo-Endpunkt ist in den Server-Metadaten nicht konfiguriert');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' ist ein Standard-Anspruch (Claim) für das Subjekt (Benutzer-ID)
clientId: '', // Client ID wird in diesem Beispiel nicht verwendet, kann aber gesetzt werden
scopes: [],
claims: userInfo,
};
};
Der folgende Code geht ebenfalls davon aus, dass der Autorisierungsserver den userinfo-Endpunkt zum Abrufen von Benutzeridentitätsinformationen unterstützt. Wenn dein Anbieter diesen Endpunkt nicht unterstützt, musst du die Dokumentation deines Anbieters für den spezifischen Endpunkt prüfen und die userinfo-Endpunkt-Variable durch die korrekte URL ersetzen.
- Python
- Node.js
Aktualisiere die whoami.py
, um die MCP Auth-Konfiguration einzubinden:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Ersetze dies durch deinen Issuer-Endpunkt
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Aktualisiere die whoami.js
, um die MCP Auth-Konfiguration einzubinden:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Ersetze dies durch deinen Issuer-Endpunkt
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
In einigen Fällen kann die Antwort des Providers fehlerhaft oder nicht dem erwarteten Metadatenformat entsprechend sein. Wenn du sicher bist, dass der Provider konform ist, kannst du die Metadaten über die Konfigurationsoption transpiliieren:
- Python
- Node.js
mcp_auth = MCPAuth(
server=fetch_server_config(
# ...other options
transpile_data=lambda data: {**data, 'response_types_supported': ['code']}
)
)
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, {
// ...other options
transpileData: (data) => ({ ...data, response_types_supported: ['code'] }),
}),
});
Wenn dein Anbieter OpenID Connect Discovery nicht unterstützt, kannst du die Metadata-URL oder Endpunkte manuell angeben. Sieh dir Weitere Möglichkeiten zur Initialisierung von MCP Auth für mehr Details an.
Nun müssen wir einen benutzerdefinierten Zugangstoken (Access token) Verifizierer erstellen, der die Benutzeridentitätsinformationen vom Autorisierungsserver mit dem vom MCP-Inspector bereitgestellten Zugangstoken abruft.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt mit den Benutzerinformationen zurückgegeben.
:param token: Das vom MCP-Inspector erhaltene Bearer-Token.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # Der Anbieter sollte den userinfo-Endpunkt unterstützen
if not endpoint:
raise ValueError(
"Userinfo-Endpunkt ist in den Auth-Server-Metadaten nicht konfiguriert."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # Standard Bearer-Token-Header
)
response.raise_for_status() # Fehler bei HTTP-Fehlern auslösen
json = response.json() # Die JSON-Antwort parsen
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' ist ein Standard-Anspruch (Claim) für das Subjekt (Benutzer-ID)
issuer=issuer, # Verwende den Aussteller (Issuer) aus den Metadaten
claims=json, # Alle Ansprüche (Claims) (JSON-Felder), die vom userinfo-Endpunkt zurückgegeben werden
)
# `AuthInfo` ist ein Pydantic-Modell, daher bedeuten Validierungsfehler meist, dass die Antwort nicht der erwarteten Struktur entspricht
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Andere Ausnahmen behandeln, die während der Anfrage auftreten können
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
* Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt mit den Benutzerinformationen zurückgegeben.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('Userinfo-Endpunkt ist in den Server-Metadaten nicht konfiguriert');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' ist ein Standard-Anspruch (Claim) für das Subjekt (Benutzer-ID)
clientId: '', // Client ID wird in diesem Beispiel nicht verwendet, kann aber gesetzt werden
scopes: [],
claims: userInfo,
};
};
Wie bereits erwähnt, definiert OAuth 2.0 keine standardisierte Methode zum Abrufen von Benutzeridentitätsinformationen. Der folgende Code geht davon aus, dass dein Anbieter einen spezifischen Endpunkt zum Abrufen von Benutzeridentitätsinformationen mit einem Zugangstoken bereitstellt. Du musst die Dokumentation deines Anbieters für den spezifischen Endpunkt prüfen und die userinfo-Endpunkt-Variable durch die korrekte URL ersetzen.
- Python
- Node.js
Aktualisiere die whoami.py
, um die MCP Auth-Konfiguration einzubinden:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Ersetze dies durch deinen Issuer-Endpunkt
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OAUTH)
mcp_auth = MCPAuth(server=auth_server_config)
Aktualisiere die whoami.js
, um die MCP Auth-Konfiguration einzubinden:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Ersetze dies durch deinen Issuer-Endpunkt
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oauth' }),
});
In einigen Fällen kann die Antwort des Providers fehlerhaft oder nicht dem erwarteten Metadatenformat entsprechend sein. Wenn du sicher bist, dass der Provider konform ist, kannst du die Metadaten über die Konfigurationsoption transpiliieren:
- Python
- Node.js
mcp_auth = MCPAuth(
server=fetch_server_config(
# ...other options
transpile_data=lambda data: {**data, 'response_types_supported': ['code']}
)
)
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, {
// ...other options
transpileData: (data) => ({ ...data, response_types_supported: ['code'] }),
}),
});
Wenn dein Anbieter OAuth 2.0 Authorization Server Metadata nicht unterstützt, kannst du die Metadata-URL oder Endpunkte manuell angeben. Sieh dir Weitere Möglichkeiten zur Initialisierung von MCP Auth für mehr Details an.
Nun müssen wir einen benutzerdefinierten Zugangstoken (Access token) Verifizierer erstellen, der die Benutzeridentitätsinformationen vom Autorisierungsserver abruft, indem er das vom MCP-Inspector bereitgestellte Zugangstoken verwendet.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt zurückgegeben, das die Benutzerinformationen enthält.
:param token: Das Bearer-Token, das vom MCP-Inspector empfangen wurde.
"""
try:
# Der folgende Code geht davon aus, dass dein Autorisierungsserver einen Endpunkt zum Abrufen von Benutzerinformationen hat,
# der das im Autorisierungsablauf ausgestellte Zugangstoken verwendet.
# Passe die URL und Header nach Bedarf entsprechend der API deines Providers an.
response = requests.get(
"https://your-authorization-server.com/userinfo",
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status() # Stelle sicher, dass wir bei HTTP-Fehlern einen Fehler auslösen
json = response.json() # Parsen der JSON-Antwort
# Der folgende Code geht davon aus, dass die Benutzerinfo-Antwort ein Objekt mit einem 'sub'-Feld ist,
# das den Benutzer identifiziert. Du musst dies ggf. entsprechend der API deines Providers anpassen.
return AuthInfo(
token=token,
subject=json.get("sub"),
issuer=auth_issuer, # Verwende den konfigurierten Aussteller (Issuer)
claims=json, # Füge alle Ansprüche (Claims / JSON-Felder) hinzu, die vom Endpunkt zurückgegeben werden
)
# `AuthInfo` ist ein Pydantic-Modell, daher bedeuten Validierungsfehler normalerweise, dass die Antwort nicht der erwarteten Struktur entspricht
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Behandle andere Ausnahmen, die während der Anfrage auftreten können
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Überprüft das bereitgestellte Bearer-Token, indem Benutzerinformationen vom Autorisierungsserver abgerufen werden.
* Wenn das Token gültig ist, wird ein `AuthInfo`-Objekt zurückgegeben, das die Benutzerinformationen enthält.
*/
const verifyToken = async (token) => {
// Der folgende Code geht davon aus, dass dein Autorisierungsserver einen Endpunkt zum Abrufen von Benutzerinformationen hat,
// der das im Autorisierungsablauf ausgestellte Zugangstoken verwendet.
// Passe die URL und Header nach Bedarf entsprechend der API deines Providers an.
const response = await fetch('https://your-authorization-server.com/userinfo', {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
// Der folgende Code geht davon aus, dass die Benutzerinfo-Antwort ein Objekt mit einem 'sub'-Feld ist,
// das den Benutzer identifiziert. Du musst dies ggf. entsprechend der API deines Providers anpassen.
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer: authIssuer,
subject: String(userInfo.sub), // Passe dies ggf. an das User-ID-Feld deines Providers an
clientId: '', // Die Client-ID wird in diesem Beispiel nicht verwendet, kann aber gesetzt werden, falls benötigt
scopes: [],
claims: userInfo,
};
};
MCP-Server aktualisieren
Wir sind fast fertig! Jetzt ist es an der Zeit, den MCP-Server zu aktualisieren, um die MCP Auth-Route und Middleware-Funktion anzuwenden und das whoami
-Tool so zu gestalten, dass es die tatsächlichen Benutzeridentitätsinformationen zurückgibt.
- Python
- Node.js
@mcp.tool()
def whoami() -> dict[str, Any]:
"""Ein Tool, das die Informationen des aktuellen Benutzers zurückgibt."""
return (
mcp_auth.auth_info.claims
if mcp_auth.auth_info # Dies wird durch die Bearer-Auth-Middleware befüllt
else {"error": "Nicht authentifiziert"}
)
# ...
bearer_auth = Middleware(mcp_auth.bearer_auth_middleware(verify_access_token))
app = Starlette(
routes=[
# Füge die Metadaten-Route hinzu (`/.well-known/oauth-authorization-server`)
mcp_auth.metadata_route(),
# Schütze den MCP-Server mit der Bearer-Auth-Middleware
Mount('/', app=mcp.sse_app(), middleware=[bearer_auth]),
],
)
server.tool('whoami', ({ authInfo }) => {
return {
content: [
{ type: 'text', text: JSON.stringify(authInfo?.claims ?? { error: 'Nicht authentifiziert' }) },
],
};
});
// ...
app.use(mcpAuth.delegatedRouter());
app.use(mcpAuth.bearerAuth(verifyToken));
Checkpoint: Das whoami
-Tool mit Authentifizierung ausführen
Starte deinen MCP-Server neu und öffne den MCP Inspector in deinem Browser. Wenn du auf die Schaltfläche "Connect" klickst, solltest du zur Anmeldeseite deines Autorisierungsservers weitergeleitet werden.
Sobald du dich angemeldet hast und zum MCP Inspector zurückkehrst, wiederhole die Schritte aus dem vorherigen Checkpoint, um das whoami
-Tool auszuführen. Dieses Mal solltest du die vom Autorisierungsserver zurückgegebenen Benutzeridentitätsinformationen sehen.
- Python
- Node.js
Sieh dir das MCP Auth Python SDK Repository für den vollständigen Code des MCP-Servers (OIDC-Version) an.
Sieh dir das MCP Auth Node.js SDK Repository für den vollständigen Code des MCP-Servers (OIDC-Version) an. Dieses Verzeichnis enthält sowohl TypeScript- als auch JavaScript-Versionen des Codes.
Abschließende Hinweise
🎊 Glückwunsch! Du hast das Tutorial erfolgreich abgeschlossen. Lass uns zusammenfassen, was wir gemacht haben:
- Einen grundlegenden MCP-Server mit dem
whoami
-Tool eingerichtet - Den MCP-Server mit einem Autorisierungsserver unter Verwendung von MCP Auth integriert
- Den MCP Inspector so konfiguriert, dass Benutzer authentifiziert und deren Identitätsinformationen abgerufen werden
Du möchtest vielleicht auch einige fortgeschrittene Themen erkunden, darunter:
- Die Verwendung von JWT (JSON Web Token) für Authentifizierung und Autorisierung
- Die Nutzung von Ressourcenindikatoren (RFC 8707), um die zuzugreifenden Ressourcen anzugeben
- Die Implementierung eigener Zugangskontrollmechanismen, wie rollenbasierte Zugangskontrolle (RBAC) oder attributbasierte Zugangskontrolle (ABAC)
Sieh dir unbedingt weitere Tutorials und die Dokumentation an, um das Beste aus MCP Auth herauszuholen.