Skip to main content
Glama
R0Wi

mcp-gateway

by R0Wi

MCP Gateway

Ein leichtgewichtiges, selbstgehostetes MCP-Aggregator-Gateway: ein öffentlicher MCP-Endpunkt vor beliebig vielen geschützten Backend-MCP-Servern, mit einem spezifikationskonformen OAuth-2.1-Autorisierungsserver, der dem MCP-Client zugewandt ist – das Element, das den meisten vorhandenen Gateways fehlt.

Claude Code / Claude.ai ──OAuth 2.1 (DCR/CIMD + PKCE)──▶ MCP Gateway ──own credentials──▶ GitHub MCP
                                                          │                              ▶ Microsoft Learn MCP
                                                          └── /mcp (Streamable HTTP)      ▶ …more backends

Entwickelt mit FastAPI + FastMCP, konfiguriert über eine einzelne YAML-Datei, speichert seinen Zustand in einer einzigen verschlüsselten SQLite-Datenbank und wird als ein kleiner, eigenständiger Container ausgeliefert – kein Reverse-Proxy erforderlich, man kann jedoch einen davor setzen, wenn TLS benötigt wird.

Funktionen

Client-seitig (MCP-Autorisierungsspezifikation, 2025-11-25):

  • OAuth-2.1-Autorisierungscode-Ablauf mit verpflichtendem PKCE (S256)

  • Dynamische Client-Registrierung (RFC 7591) unter /register — claude mcp add funktioniert ohne vorab geteilte Zugangsdaten

  • Client-ID-Metadaten-Dokumente (CIMD) – HTTPS-URLs als Client-IDs, einschließlich private_key_jwt-Client-Authentifizierung, bekanntgegeben über client_id_metadata_document_supported: true

  • Autorisierungsserver-Metadaten (RFC 8414) + OIDC-Discovery-Alias

  • Metadaten der geschützten Ressource (RFC 9728); 401-Antworten enthalten WWW-Authenticate: Bearer resource_metadata="…", wie es der Connector von Claude verlangt

  • Ressourcenindikatoren (RFC 8707) werden akzeptiert und an die ausgegebenen Token gebunden

  • Kurzlebige, undurchschaubare Zugriffstokens, rotierende Refresh-Tokens, einmalig nutzbare Autorisierungscodes – alle nur gehasht gespeichert; Client-Datensätze im Ruhezustand verschlüsselt

  • Loopback-Weiterleitungs-URIs werden portunabhängig abgeglichen (die Claude-Code-CLI registriert einen Port und autorisiert mit einem anderen); Nicht-Loopback-URIs erfordern die exakte Registrierung

  • Schlanke Svelte-5-Benutzeroberfläche für Login und Zustimmung (eine einzige lokale Identität aus der Konfigurationsdatei)

Backend-seitig:

  • none – öffentliche Server (z. B. Microsoft Learn MCP)

  • bearer – statische Token-Injektion (Authorization: Bearer …, z. B. PATs)

  • headers – beliebige statische Header (API-Schlüssel)

  • oauth – vollwertiger OAuth-Client nach der MCP-Spezifikation: Metadaten-Discovery, CIMD, sofern das Upstream-AS dies unterstützt (das Gateway hostet sein eigenes Client-Metadaten-Dokument), DCR-Fallback, PKCE, automatisches Refresh. Einmal über den Browser verbunden; Token werden verschlüsselt (Fernet) in SQLite gespeichert.

  • Das Gateway-Token des Clients wird nie weiter übergeben an den Upstream (kein Token-Passthrough, wie von der Spezifikation gefordert); Backends sehen ausschließlich Zugangsdaten, die das Gateway hält.

Aggregation:

  • Tools/Ressourcen/Prompts werden pro Backend namespacediert: github_create_issue, msdocs_microsoft_docs_search, …

  • Live-Proxy über Streamable HTTP; ein heruntergefahrenes oder noch nicht verbundenes Backend entfernt nur seine eigenen Tools, anstatt das Gateway zu beeinträchtigen

  • Integriertes gateway_status-Tool

Related MCP server: MCP OAuth Test

Schnellstart

cp config.example.yaml config.yaml
$EDITOR config.yaml                                   # set public_url, users, backends
cp .env.example .env
$EDITOR .env                                           # set MCP_GATEWAY_ENCRYPTION_KEY (openssl rand -base64 32)
docker compose up -d

Das Gateway läuft eigenständig und lauscht auf :8000; docker compose übernimmt MCP_GATEWAY_ENCRYPTION_KEY automatisch aus .env. Platzieren Sie es hinter einem Reverse-Proxy Ihrer Wahl für TLS oder legen Sie den Port direkt offen.

Erzeugen Sie einen Passwort-Hash für die Konfigurationsdatei:

docker compose run --rm mcp-gateway mcp-gateway hash-password

Claude Code verbinden (CLI)

claude mcp add --transport http gateway https://mcp.example.com/mcp

Claude Code entdeckt den Autorisierungsserver des Gateaways, registriert sich über DCR oder seine CIMD-Client-ID und öffnet Ihren Browser: Melden Sie sich mit einem Benutzer aus config.yaml an, genehmigen Sie alles, fertig. Keine Token müssen eingefügt werden.

Claude.ai / Claude Code Web verbinden (benutzerdefinierter Connector)

Fügen Sie https://mcp.example.com/mcp als benutzerdefinierten Connector hinzu. Die Browser-Weiterleitung an https://claude.ai/api/mcp/auth_callback durchläuft denselben Login-/Zustimmungsablauf.

OAuth-Backends verbinden

Öffnen Sie https://mcp.example.com/ui/backends, melden Sie sich an und drücken Sie Verbinden bei jedem OAuth-Backend (z. B. GitHub MCP). Sie werden genau einmal zum Autorisierungsserver des Backends umgeleitet; anschließend erneuert das Gateway Token automatisch.

Konfiguration

Alles befindet sich in einer YAML-Datei (siehe config.example.yaml). Werte unterstützen ${ENV_VAR} beziehungsweise ${ENV_VAR:-default}-Erweiterung.

server:
  public_url: https://mcp.example.com   # behind your reverse proxy

auth:
  encryption_key: ${MCP_GATEWAY_ENCRYPTION_KEY}   # encrypts secrets at rest
  users:
    - username: admin
      password_hash: "$2b$12$…"          # mcp-gateway hash-password
  access_token_expiry_seconds: 3600
  refresh_token_expiry_seconds: 2592000

storage:
  path: /data/gateway.db                 # SQLite; the only state

backends:
  github:                                # → tools namespaced github_*
    url: https://api.githubcopilot.com/mcp/
    auth:
      type: oauth
      # GitHub's authorization server supports neither CIMD nor DCR, so
      # register a GitHub OAuth App and provide its credentials directly:
      client_id: ${GITHUB_OAUTH_CLIENT_ID}
      client_secret: ${GITHUB_OAUTH_CLIENT_SECRET}
  microsoft-docs:                        # → tools namespaced microsoft-docs_*
    url: https://learn.microsoft.com/api/mcp
    auth: { type: none }
  something-with-a-pat:
    url: https://example.com/mcp
    auth: { type: bearer, token: "${SOME_PAT}" }

Das Hinzufügen eines Backends ist reine Konfiguration – keine Codeänderungen.

Backend-Authentifizierungsreferenz

Typ

Felder

Verhalten

none

–

keine Zugangsdaten gesendet

bearer

token

Authorization: Bearer <token> bei jeder Anforderung

headers

headers: {Name: value}

statische Header (API-Schlüssel usw.)

oauth

scopes, prefer_dcr, client_id, client_secret

vollwertiger OAuth-Client: CIMD → DCR-Fallback, PKCE, Refresh, verschlüsselter Speicher

Bei oauth-Backends hostet das Gateway sein eigenes Client-ID-Metadaten-Dokument unter <public_url>/oauth/client-metadata.json und verwendet es als Client-ID, sobald der Upstream-AS CIMD-Unterstützung bewirbt (dann ist eine HTTPS-public_url erforderlich). Andernfalls wird die Dynamische Client-Registrierung (DCR) verwendet. Wenn nicht der das Upstream-AS keines von beiden unterstützt (z. B. der von GitHub), setzen Sie client_id (und client_secret, falls die App vertraulich ist), um einen vorregistrierten OAuth-Client zu verwenden – CIMD/DCR werden dann vollständig übersprungen.

Logging

Das Gateway protokolliert nach stdout/stderr (docker logs, docker compose logs -f), on standard INFO: Start/Herunterfahren, Konfigurationsübersicht, Anmeldeversuche, OAuth-Autorisierung-/Einwilligung/Token-Ausgabe, Backend-Verbindung/Trennung sowie den Mount-Status der Backends. DEBUG fügt feinkörniger Details hinzu (Client-Konstruktion, Token-Rotation, CIMD-Aktualisierung, Haushaltsführung des Speichers). Zu keiner Protokollstufe werden jemals Zugangsdaten oder Token protokolliert.

Legen Sie die Stufe über die Umgebungsvariable MCP_GATEWAY_LOG_LEVEL fest (debug, info, warning, error oder critical):

# .env (picked up by docker compose)
MCP_GATEWAY_LOG_LEVEL=debug
# or inline
docker compose run --rm -e MCP_GATEWAY_LOG_LEVEL=debug mcp-gateway

docker-compose.yml übergibt diese Variable jetzt bereits an die Entiät; wenn keine gesetzt ist, wird standardmäßig info verwendet.

Außerhalb von Docker funktioniert --log-level bei mcp-gateway run genauso und hat Vorrang vor der Umgebungsvariable:

mcp-gateway run -c config.yaml --log-level debug

Endpunkte

Pfad

Zweck

/mcp

MCP-Endpunkt (Streamable-Web)

/.well-known/oauth-protected-resource[/mcp]

Metadaten der geschützten Ressource (RFC 9728)

/.well-known/oauth-authorization-server

Autorisierungsserver-Metadaten (RFC 8414) + OIDC-Alias

/authorize, /token, /register, /revoke

OAuth-2.1-Endpunkte (PKCE, DCR, Widerruf)

/ui/authorize

Login / Zustimmung (Svelte 5)

/ui/backends

Backend-Verbindungsstatus / verbinden / trennen

/oauth/client-metadata.json

eigener CIMD-Dokument des Gateways (Upstream-Strecke)

/oauth/connect/<backend>, /oauth/callback

Upstream-OAuth-Verbindungsablauf

/healthz

Liveness-Check

Sicherheitshinweise

  • PKCE (S256) ist verpflichtend; Autorisierungscodes sind einmalig nutzbar und verfallen nach 5 Minuten.

  • Refresh-Tokens rotieren bei jeder Verwendung (Anforderung für öffentliche Clients in OAuth 2.1).

  • Zugriffs-, Refresh-Tokens und Autorisierungscodes werden ausschließlich als SHA-256-Hashes gespeichert.

  • Registrierte Client-Datensätze und Upstream-Zugangsdaten werden im Ruhezustand mit Fernet verschlüsselt (auth.encryption_key; Passphrasen werden mit scrypt und pro Datenbank Salt abgeleitet).

  • Der Zustimmungsbildschirm nennt den Client und das exakte Umleitungsziel und warnt bei Loopback-Weiterleitungen (gemäß CIMD-Vorgaben zur Vermeidung von Localhost-Impersonation).

  • Tokens, die an MCP-Clients ausgegeben werden, werden niemals an Backends weitergeleitet; Backend-Zugangsdaten erreichen nie MCP-Clients.

  • Sitzungen sind signiert (itsdangerous), HttpOnly, SameSite=Lax, Secure bei HTTPS.

  • Zugangsdaten werden nicht protokolliert.

Entwicklung

uv venv && uv pip install -e ".[dev]"     # or: pip install -e ".[dev]"
(cd ui && npm install && npm run build)   # build the Svelte UI
pytest                                    # 35 tests incl. full e2e OAuth flows
mcp-gateway run -c config.yaml

Die Testsuite startet echte Gateways (und eine zweite Instanz, die als OAuth-geschützter Upstream dient) und durchläuft vollständige DCR/CIMD- und PKCE-Abläufe über HTTP.

Architektur

  • src/mcp_gateway/oauth_server.py – der client-zugewandte OAuth-AS. Er baut auf den Autorisierungsserver-Handlern der MCP-SDK und dem CIMD-Manager von FastMCP auf, statt Protokollcode von Hand zu schreiben; das Gateway ergänzt SQLite-Persistenz, den Login-/Zustimmungs-Transaktions Flow und die Richtlinie für Token-Ausgabe/-Rotation.

  • src/mcp_gateway/upstream.py – Backend-Clients. OAuth-Backends verwenden den offiziellen OAuthClientProvider des SDK (Discovery, CIMD/DCR, Refresh) mit verschlüsseltem SQLite-Tokenspeicher und einem über Browser gesteuerten Verbindungsablauf.

  • src/mcp_gateway/gateway.py – FastMCP-Server; jedes Backend wird als Live-Proxy unter seinem Namespace eingebunden.

  • src/mcp_gateway/app.py / web.py – FastAPI-App: JSON-API für die UI, Upstream-Callback, CIMD-Dokument, statische Svelte-App; die FastMCP-App (MCP-Endpunkt + OAuth-Routen + Well-Known) wird im Root-Verzeichnis gemounted.

  • ui/ – Svelte 5 + Vite SPA (Anmeldung, Zustimmung, Backends).

Bewusst als Ein-Instanz-Design (SQLite + In-Memory-Verbindungsabläufe). Läuft eigenständig; Sie können es hinterbringen vorhandenen Reverse-Proxy für TLS-Terminierung und sichern eine einzige Datei.

Maintenance

ActivityMaintained
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Aggregates multiple MCP servers behind a single, secure endpoint with unified tool/resource discovery, OAuth authentication, and resilient request routing. Enables users to manage and interact with multiple MCP backends through one centralized interface with load balancing and circuit breakers.
    2
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Multi-tenant MCP server with OAuth 2.1 authorization, enabling tenant-scoped tool access and audit logging.
    -
  • A
    license
    A
    quality
    C
    maintenance
    A federated MCP gateway that consolidates multiple plain-HTTP backends into a single, OAuth-protected MCP server, enabling agents to access diverse tools through one endpoint with centralized authentication and audit.
    5
    12
    MIT