mcp-oauth-test
FastMCP OIDC Server
Dies ist ein MCP-Server, der mit FastMCP geschrieben und durch OIDC-Login geschützt ist. Er verwendet den OIDCProxy von FastMCP: Der MCP-Client authentifiziert sich über die vom Server bereitgestellten OAuth-Metadaten, während der eigentliche Login und Token-Austausch an den QA-OIDC-Provider weitergeleitet werden.
Derzeit ist die QA MGT OpenAPI angebunden, die MCP-Tools für Trainee, Bestellungen, Produkte, Kunden, Campus-Recruiting und internationale Rekrutierung generiert.
Die OIDC-Discovery-Adresse ist standardmäßig wie folgt konfiguriert:
https://auth-qa.drillinsight.com/.well-known/openid-configurationAuthentifizierungsvorbereitung
Registrieren Sie zuerst eine OAuth-Anwendung unter auth-qa.drillinsight.com und fügen Sie die folgende Callback-Adresse zur Whitelist hinzu:
http://localhost:8000/auth/callbackWenn Sie auf einer anderen Adresse bereitstellen, ersetzen Sie http://localhost:8000 durch den Wert von BASE_URL. Die Callback-Adresse muss exakt mit dem BASE_URL von FastMCP übereinstimmen.
Lokale Ausführung
cp .env.example .env
# 编辑 .env,至少填写 OIDC_CLIENT_ID 和 OIDC_CLIENT_SECRET
uv sync
uv run mcp-oidc-serverSie können das Modul auch direkt ausführen:
uv run python -m oidc_mcp_server.serverDer Dienst lauscht standardmäßig auf http://127.0.0.1:8000. Wenn der MCP-Client auf einer anderen Maschine oder in einem Container läuft, setzen Sie eine für den Client erreichbare BASE_URL und eine geeignete HOST-Adresse (z. B. 0.0.0.0).
Claude Code Plugin
Das Repository enthält einen privaten Claude-Code-Marketplace und ein MCP-Plugin:
.claude-plugin/marketplace.json
└── plugins/mcp-oauth-test/
├── .claude-plugin/plugin.json
├── .mcp.json
└── README.mdDas Plugin verbindet Claude Code lediglich mit dem bereits bereitgestellten Remote-MCP-Dienst und startet keinen lokalen Python-Dienst. Für Entwicklungs- und Testzwecke kann es direkt geladen werden:
claude --plugin-dir ./plugins/mcp-oauth-testDas Plugin ist fest mit dem MCP-Server der Entwicklungsumgebung verbunden:
https://api-mcp-oauth-dev.beaconfireinc.com/mcpEs kann auch über den privaten Marketplace installiert werden:
/plugin marketplace add /path/to/mcp-oauth-test
/plugin install mcp-oauth-test@authsome-internalDas aktuelle Marketplace-Root-Verzeichnis ist das Repository-Root. Bitte halten Sie diesen Marketplace in einem privaten GitHub-Repository des Unternehmens und übermitteln Sie ihn nicht an einen öffentlichen Marketplace. Für gemeinsame Umgebungen sollten Sie HTTPS-Adressen verwenden und den Zugriff auf Unternehmensbenutzer auf der Seite des IdP und des MCP-Servers beschränken.
Warum OIDCProxy
Der Upstream auth-qa.drillinsight.com muss kein DCR oder CIMD unterstützen. OIDCProxy ist genau für dieses Szenario gedacht:
ChatGPT ── MCP OAuth / CIMD ──> FastMCP OIDCProxy
│
└── 固定 client_id/client_secret ──> auth-qa.drillinsight.comIm Upstream muss nur die OAuth-Anwendung FastMCP vorab registriert werden, und ${BASE_URL}/auth/callback muss konfiguriert werden. Das von ChatGPT verwendete CIMD wird von der FastMCP-Proxy-Schicht verarbeitet und nicht an den Upstream-OAuth-Server weitergeleitet.
ChatGPT CIMD-Konfiguration
Wählen Sie beim Erstellen eines benutzerdefinierten MCP in ChatGPT unter den erweiterten OAuth-Einstellungen für „Client-Registrierung“ die folgende Option:
客户端标识元数据文档(CIMD)Die vom aktuellen ChatGPT-Connector generierten Informationen sind:
CIMD Client ID / 客户端元数据 URL:
https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
ChatGPT Callback URL:
https://chatgpt.com/connector/oauth/0Buhw3sHVv1-Die CIMD-URL selbst ist die client_id, die ChatGPT beim Zugriff auf den FastMCP-OAuth-Proxy verwendet. Sie muss nicht und sollte nicht beim Upstream auth-qa.drillinsight.com registriert werden.
Dieses Projekt enthält zwei verschiedene Ebenen von OAuth-Client-IDs:
OAuth-Kette |
| Konfigurationsort |
ChatGPT → FastMCP OIDCProxy |
| Von ChatGPT automatisch bereitgestellt; nach Auswahl von CIMD keine manuelle Eingabe erforderlich |
FastMCP OIDCProxy → |
|
|
Der entsprechende Datenfluss ist:
ChatGPT
│ client_id=https://chatgpt.com/oauth/0Buhw3sHVv1-/client.json
▼
FastMCP OIDCProxy
│ client_id=app_74a4b555-5b87-4212-9dda-d584fa78caf8
▼
auth-qa.drillinsight.comDie Umgebungsvariablen des MCP-Servers:
OIDC_CLIENT_ID=app_74a4b555-5b87-4212-9dda-d584fa78caf8
OIDC_CLIENT_SECRET=<上游 OAuth Server 颁发的客户端密钥>Der Upstream-OAuth-Server muss nur die FastMCP-Callback-Adresse für die app_...-Anwendung konfigurieren:
https://heroic-verbally-crawdad.ngrok-free.app/auth/callbackKonfigurieren Sie die ChatGPT-Callback-Adresse https://chatgpt.com/connector/oauth/... nicht am Upstream-OAuth-Server; diese Adresse wird von der FastMCP-Proxy-Schicht nach Abschluss der Authentifizierung verwendet.
Zu Beginn der Authentifizierung sollte im normalen Log zuerst die CIMD-Client-ID von ChatGPT erscheinen:
CIMD document fetched and validated
GET /authorize?client_id=https://chatgpt.com/oauth/.../client.json ... 302Anschließend verwendet FastMCP app_74a4b555-..., um zum Upstream-OAuth-Server weiterzuleiten.
MCP-Client-Konfiguration
Konfigurieren Sie die MCP-Adresse wie folgt:
http://localhost:8000/mcpFastMCP stellt die folgenden Authentifizierungs-Discovery-Adressen bereit:
http://localhost:8000/.well-known/oauth-authorization-server
http://localhost:8000/.well-known/oauth-protected-resource/mcpDer Client sollte diese MCP/OAuth-Discovery-Endpunkte automatisch lesen. Nach erfolgreichem Login können zwei geschützte Tools aufgerufen werden:
ping: Gesundheitscheck.who_am_i: Gibt dieclient_id, Scopes und Claims zurück, die FastMCP aus dem aktuellen Authentifizierungstoken extrahiert.
Konfigurationsoptionen
Umgebungsvariable | Erforderlich | Standardwert | Beschreibung |
| Ja | - | Upstream-OIDC-Client-ID |
| Eines von beiden | - | Geheimnis des vertraulichen Clients |
| Eines von beiden | - | Signaturschlüssel für öffentliche PKCE-Clients oder FastMCP-Token in der Produktion |
| Nein | QA-Discovery-URL | OIDC-Discovery-Adresse |
| Nein |
| Öffentliche Adresse des MCP-Servers |
| Nein |
| Scope für OAuth-Autorisierungsanfragen/Standardwerbung; nicht für die Access-Token-Scope-Validierung |
| Nein | OIDC-Discovery-Issuer | JWT- |
| Nein |
| JWKS-Adresse für benutzerdefinierte Token-Issuer |
| Nein | - | Optionaler JWT- |
| Nein |
| Lauschadresse |
| Nein |
| Lauschport |
| Nein | QA-MGT-Adresse | Basis-URL für tatsächliche MGT-API-Aufrufe |
| Nein |
| Pfad zur lokalen OpenAPI-Spezifikation |
Setzen Sie in der Produktion explizit einen zufälligen JWT_SIGNING_KEY und verwenden Sie eine HTTPS-BASE_URL. Committen Sie weder .env noch Client-Secrets in Git.
Benutzerdefinierter Token-Issuer
Wenn der iss des Tokens nicht der vom OIDC-Discovery zurückgegebene Issuer ist, sondern von der Auth-Middleware in eine Mandantenadresse umgeschrieben wird, z. B.:
实际 token iss:
https://api-authsome-qa.drillinsight.com/auth-middleware/t_adecdb63-afab-4346-a1aa-b50bbbae7aee/Setzen Sie:
OIDC_TOKEN_ISSUER=https://api-authsome-qa.drillinsight.com/auth-middleware/t_adecdb63-afab-4346-a1aa-b50bbbae7aee/
OIDC_JWKS_URI=https://auth-qa.drillinsight.com/oauth/jwksOIDC_CONFIG_URL wird weiterhin für die OAuth-Login- und Autorisierungs-Endpunkt-Discovery verwendet; OIDC_TOKEN_ISSUER dient nur zur Validierung des iss des JWT-Access-Tokens. Beide können unterschiedlich sein. OIDC_TOKEN_ISSUER muss exakt mit dem iss im Token übereinstimmen, einschließlich des abschließenden /.
Das aktuelle Projekt validiert weder den scope- noch den scp-Claim des Access-Tokens, da historische MGT-Tokens ein nicht standardkonformes Scope-Format verwenden. OIDC_REQUIRED_SCOPES wird weiterhin für OAuth-Autorisierungsanfragen verwendet, blockiert jedoch keine gültigen Tokens ohne standardkonforme Scope-Claims. Signatur-, Issuer-, Audience-, Ablaufzeit- und JWKS-Validierung bleiben erhalten.
QA MGT OpenAPI-Anbindung
Die QA-OpenAPI-Spezifikation wurde fest unter folgendem Pfad gespeichert:
specs/mgt-qa-openapi.jsonMCP greift zur Laufzeit nicht auf die Online-/api-docs zu, sodass die zukünftige Produktionsumgebung ohne offene API-Dokumentation weiterhin funktioniert. Über MGT_API_BASE_URL kann die tatsächliche API-Adresse umgeschaltet werden. Das Docker-Image kopiert specs/mgt-qa-openapi.json nach /app/specs/mgt-qa-openapi.json und setzt MGT_OPENAPI_SPEC_PATH automatisch.
Der in der ersten Version freigegebene API-Umfang:
/api/v1/user/current
/course/list
/batch/list
/batch/trainee/list
/equity/userequity/give
/api/v1/order/**
/api/v1/item/**
/api/v1/open/getSku*
/api/v1/customers
/api/v1/campus-recruitment/**(排除 export)
/api/v1/recruitment-info/**(排除 export)Die Schnittstelle für Bestellungs-Zahlungslink wird gemäß den aktuellen Anforderungen angebunden:
/api/v1/order/queryPayLink
/api/v1/order/reGenaratePayLinkWeiterhin ausgeschlossen sind Rückerstattungs-, Zahlungs-Callback- und Kundendatenexport-Schnittstellen:
/mall/v1/order/refund
/alipay/**
/stripe/**
/weixin/refund/**
/api/v1/customers/export
/api/v1/campus-recruitment/export
/api/v1/recruitment-info/exportBei jedem MGT-Aufruf holt der OpenAPI-Client das Upstream-OAuth-Access-Token des Benutzers aus der aktuellen FastMCP-Anfrage und sendet:
Authorization: Bearer <user access token>
X-Application-Id: <token.app_id>Dabei muss X-Application-Id nicht zusätzlich konfiguriert werden; es wird direkt aus dem app_id-Claim des validierten JWT gelesen. Tokens ohne app_id werden abgelehnt, um unvollständige Anfragen an MGT zu vermeiden.
Daher muss MGT den von auth-qa.drillinsight.com ausgestellten Benutzer-Tokens vertrauen und die Berechtigungssteuerung basierend auf der Benutzeridentität durchführen.
Fehlerbehebung bei ChatGPT CIMD-Timeout
Wenn das Log Folgendes enthält:
CIMD fetch failed for https://chatgpt.com/.../client.json: Timeout fetching
Unregistered client_id=https://chatgpt.com/.../client.jsonbedeutet dies, dass FastMCP nicht direkt auf die von ChatGPT gehosteten Client-Metadaten zugreifen kann. Wenn die aktuelle Maschine für den Zugriff auf das Internet über einen vertrauenswürdigen ausgehenden Proxy gehen muss, konfigurieren Sie:
FASTMCP_SSRF_TRUST_PROXY=true
HTTPS_PROXY=http://127.0.0.1:7897Stoppen und starten Sie den Dienst dann vollständig neu. Das Programm lädt automatisch die .env im Projektstamm, bevor FastMCP importiert wird; FastMCP führt standardmäßig DNS-Validierung und IP-Pinning für CIMD/JWKS-Anfragen durch und verwendet daher nicht automatisch normale Proxy-Umgebungsvariablen. Wenn diese Option aktiviert ist, wird die SSRF-Schutzverantwortung an den angegebenen Proxy übertragen und NO_PROXY ignoriert. Aktivieren Sie sie nur für vertrauenswürdige Proxys.
Das erste POST /mcp 401 im Log ist der Client, der vor der Authentifizierung geschützte Ressourcen abtastet; die 404-Antworten auf mehrere /.well-known/...-Adressen sind ebenfalls Kompatibilitätstests von ChatGPT. Solange /.well-known/oauth-authorization-server 200 zurückgibt, sind sie nicht die Ursache dieses Fehlers.
Wenn das Log Unregistered client_id=app_... oder eine andere Nicht-URL-Client-ID anzeigt, bedeutet dies, dass ChatGPT eine alte DCR-Registrierung zwischengespeichert hat, die aus dem Server-Speicher verloren gegangen ist. Fixieren Sie JWT_SIGNING_KEY, starten Sie den Dienst neu und löschen Sie dann das benutzerdefinierte MCP in ChatGPT und erstellen Sie es neu, damit es /register erneut aufruft. Ein erneuter Login-Versuch stellt die dem Server unbekannte alte Client-ID nicht wieder her.
Tests
uv run pytestThis server cannot be deployed
Maintenance
Related MCP Connectors
- mcp-serverOAuthio.klokin
MCP server exposing klokin time-tracking operations (employees, time entries, stores) to AI clients.
MCP server for AI access to Swagger by SmartBear.
MCP server for Product Management
Read-only MCP server for ClassQuill, a tutoring-business-management platform.