Skip to main content
Glama
izambasiron

outsystems-mcp-relay

by izambasiron

outsystems-mcp-relay

Ein leichtgewichtiges, generisches stdio → Remote-MCP-Relay mit OAuth, plus einem RFC-9207-Issuer-Override für Remote-Server, deren veröffentlichte OAuth-Metadaten nicht mit der Autorisierungsantwort übereinstimmen. Keine Laufzeitabhängigkeiten. Eine einzige Datei.

stdio (your MCP client)  ⇄  outsystems-mcp-relay  ⇄  remote MCP server (Streamable HTTP)

Warum es das gibt

Einige Remote-MCP-Bereitstellungen sind ein Reverse-Proxy vor Keycloak (das OutSystems Developer Cloud MCP-Gateway ist eines davon). Sie veröffentlichen OAuth-Metadaten, deren issuer die Proxy-URL ist (z. B. https://<tenant>/mcp), aber der Autorisierungsserver stempelt seinen echten Issuer in den iss-Parameter der Autorisierungsantwort (z. B. https://<tenant>/auth/realms/<realm>).

RFC-9207-konforme Clients müssen diese Abweichung ablehnen, daher schlägt der OAuth-Login auf jeder Plattform fehl — Claude Code, pi, Cursor, Codex, um nur einige zu nennen. Dieses Relay ermöglicht es dir, iss gegen den echten Backend-Issuer zu validieren, während alle anderen OAuth-Prüfungen streng bleiben. Für normale Server verhält es sich wie ein einfaches Relay.

Related MCP server: mcp-auth-proxy

Wann man es verwenden sollte

Probiere zuerst die offizielle direkte Verbindung aus — richte deine Plattform direkt auf die Remote-MCP-URL aus, ohne Relay dazwischen. Greife nur dann zu diesem Relay, wenn das mit dem obigen RFC-9207-Issuer-Mismatch-Fehler fehlschlägt.

Das existiert ausschließlich, um diesen einen serverseitigen Bug zu umgehen. Es macht nichts besser als der offizielle Weg, sobald der Bug nicht mehr vorhanden ist — also wenn OutSystems es mandantenweit behebt oder dein Mandant das Problem nie hatte, entferne das Relay und verbinde dich direkt. Das Relay teilt dir mit, wann das der Fall ist: Bei einem erfolgreichen Login prüft es, ob eine Issuer-Korrektur tatsächlich nötig war, und wenn nicht, gibt es einen Hinweis auf stderr aus. Warte nicht auf eine „Wird das noch gebraucht?"-Überprüfung — wenn du diesen Hinweis siehst, wechsle sofort zurück zur offiziellen direkten Verbindung.

Installation

Erfordert Node.js ≥ 20. Keine Abhängigkeiten — nur die Datei.

npm install -g outsystems-mcp-relay      # recommended
# or, without a global install:
npx outsystems-mcp-relay <remote-url> ...

Du musst dieses Repo nicht klonen, um das Relay zu nutzen. Installiere es über npm (oder verwende npx) und fertig. Klone es nur, wenn du den Quellcode (eine einzelne Datei mit ~500 Zeilen) prüfen oder dazu beitragen möchtest.

Verwendung

outsystems-mcp-relay <remote-url> [options]

  --as-metadata-url <url>   OAuth AS metadata URL (default: discover from remote-url)
  --expected-issuer <url>   Override the RFC 9207 expected issuer (the proxy fix)
  --client-id <id>          Pre-registered client id (skips dynamic registration)
  --bearer <token>          Static bearer token mode (skips OAuth entirely)
  --force                   Ignore cached tokens and re-authenticate
  --no-open                 Print the authorization URL instead of opening a browser
  --help                    Show help

Generisches Beispiel (normaler Remote-Server)

// mcp.json
{
  "mcpServers": {
    "my-remote": {
      "command": "outsystems-mcp-relay",
      "args": ["https://api.example.com/mcp"]
    }
  }
}

OutSystems-Beispiel (Issuer-Mismatch)

{
  "mcpServers": {
    "outsystems": {
      "command": "outsystems-mcp-relay",
      "args": ["https://<tenant>.outsystems.dev/mcp"]
    }
  }
}

Kein --expected-issuer nötig — das Relay erkennt automatisch den echten Autorisierungsserver-Issuer aus der Autorisierungs-Weiterleitung (Keycloak-Realm-Setups). Füge nur dann --expected-issuer https://<tenant>.outsystems.dev/auth/realms/<realm-id> hinzu, wenn die automatische Erkennung fehlschlägt (ein Nicht-Keycloak-Server): Die OAuth-Fehlermeldung gibt den Realm aus — der empfangene Wert ist der zu verwendende Wert. Die automatische Erkennung übernimmt einen Cross-Origin-Kandidaten nur, wenn dessen Issuer durch die eigenen Metadaten des Realms bestätigt wird (über die Origin-Allowlist erreichbar); für einen wirklich separaten IdP-Host übergib --expected-issuer (oder --as-metadata-url, um ihn vorab auf die Allowlist zu setzen).

Beim ersten Aufruf öffnet das Relay einen Browser zur Anmeldung (oder gibt die URL mit --no-open aus). Tokens werden zwischengespeichert und automatisch aktualisiert.

Installation über eine KI (diesen Text einfügen)

Füge dies in Claude Code, pi, Cursor oder eine beliebige KI-Plattform ein:

Install the OutSystems MCP fix (outsystems-mcp-relay). The official OutSystems
MCP fails OAuth on every AI harness with an RFC 9207 issuer mismatch — a
server-side bug in the gateway's Keycloak setup.
Step 1: run `npm install -g outsystems-mcp-relay`.
Step 2: ask me for my OutSystems tenant hostname (something like
`mycompany.outsystems.dev`).
Step 3: when I tell you, replace the broken server:
  `claude mcp remove outsystems`
  `claude mcp add -s user --transport stdio outsystems -- outsystems-mcp-relay https://<my-tenant>/mcp`
  (substitute my actual tenant. No other flags needed — the relay auto-detects
  the real authorization-server issuer; if auto-detection can't, ask me to paste
  the OAuth error and use its "received" URL as `--expected-issuer`.)
Step 4: tell me to restart Claude Code, then ask anything OutSystems-related.
The first tool call opens a browser for sign-in (or prints the URL with
`--no-open`).

Claude-Code-Schnellstart (OutSystems-Issuer-Mismatch)

Der Fehler, den du siehst, sieht so aus:

Issuer mismatch in authorization response (RFC 9207):
expected "https://<tenant>.outsystems.dev/mcp",
received "https://<tenant>.outsystems.dev/auth/realms/<realm-id>"

In einem Terminal (nicht innerhalb von Claude Code):

npm install -g outsystems-mcp-relay

# 1. remove the broken HTTP entry
claude mcp remove outsystems

# 2. add the relay as a local stdio server — no other flags needed: it
#    auto-detects the real authorization-server issuer
claude mcp add -s user --transport stdio outsystems -- \
  outsystems-mcp-relay \
  https://<tenant>.outsystems.dev/mcp

Starte dann Claude Code neu. Beim ersten OutSystems-Toolaufruf öffnet das Relay einen Browser zur Anmeldung (füge --no-open hinzu, wenn du die URL lieber selbst einfügen möchtest). Tokens werden zwischengespeichert, sodass spätere Sitzungen die Anmeldung überspringen. Überprüfe mit /mcp (der Server sollte verbunden sein) und einem einfachen „list my environments".

Du musst den Realm-Issuer nicht selbst ermitteln. Das Relay erkennt ihn automatisch aus der Autorisierungs-Weiterleitung. Falls die automatische Erkennung nicht funktioniert (ein Nicht-Keycloak-Server), gibt die Fehlermeldung den empfangenen Wert aus — dieser ist der --expected-issuer-Wert.

So funktioniert es

  • Protokollagnostische Durchreichung: liest zeilenweise JSON-RPC von stdin, sendet jeden Frame unverändert per POST an den Remote-Server und schreibt die JSON-RPC-Antwort zurück nach stdout. Keine Tool-Semantik hier — funktioniert für Tools, Ressourcen, Prompts, alles.

  • Behandelt Streamable-HTTP-Details: Mcp-Session-Id-Echo, direkte JSON-Antworten und 202/text/event-stream-Antworten (SSE-Zusammenführung).

  • OAuth: ermittelt die Autorisierungsserver-Metadaten, registriert dynamisch einen öffentlichen Client (PKCE S256), öffnet den Browser, validiert state und iss, tauscht den Code aus und aktualisiert Tokens bei 401. --expected-issuer legt den Issuer fest, gegen den iss validiert wird — die Lösung für Proxy/Keycloak-Mismatches.

  • Anfragen werden serialisiert (keine verschachtelten Antworten auf stdout).

Sicherheit

  • RFC 9207 durchgesetzt: iss wird nur validiert, wenn der Autorisierungsserver es tatsächlich sendet (fehlt es = der AS implementiert RFC 9207 nicht, keine Prüfung; vorhanden = strikter String-Vergleich gegen den erwarteten Issuer). --expected-issuer ermöglicht einen anderen erwarteten Wert — es deaktiviert niemals die Validierung.

  • Origin-Allowlist: Das Relay kontaktiert nur die konfigurierte Remote-Origin (und eine explizit angegebene --as-metadata-url). Weiterleitungen werden manuell durchlaufen und jeder Hop ist auf der Allowlist (307/308 erhalten den Request-Body; 301/302/303 wechseln gemäß HTTP-Semantik zu GET), und Authorization/Cookie werden entfernt, wenn eine Weiterleitung die Origin wechselt (wie beim nativen fetch). Kein SSRF.

  • PKCE S256 + zufälliger state (validiert) + Callback-Server nur auf localhost mit einem ephemeren Port.

  • Protokolliert niemals Geheimnisse: Tokens und Autorisierungscodes erscheinen nie in der Ausgabe (alle Diagnosen gehen nach stderr; stdout transportiert nur Protokollnachrichten).

  • Tokens werden unter ~/.mcp-auth/outsystems-mcp-relay-<sha1(url)>.json mit 0600-Berechtigungen gespeichert — die Ökosystem-Konvention (gleiche Speicherstruktur wie mcp-remote). OS-Keychain-Speicherung ist eine geplante Erweiterung; siehe Nicht-Ziele.

Testen

npm test                # mock-server protocol test (passthrough, session-id, SSE, 401)
npm run test:e2e -- <remote-url> --expected-issuer <issuer>   # real-tenant round trip

Fehlerbehebung

Symptom

Lösung

Issuer mismatch ... expected "…/mcp", received "…/auth/realms/…"

Normalerweise erledigt die automatische Erkennung das ohne zusätzliche Flags. Falls nicht, übergib die empfangene URL als --expected-issuer — der Fehler gibt sie für dich aus.

authentication failed nach langer Inaktivität

Das zwischengespeicherte Token ist abgelaufen und die Aktualisierung fehlgeschlagen. Führe es mit --force erneut aus (oder lösche die Datei in ~/.mcp-auth/), um dich neu zu authentifizieren.

Browser öffnet sich nicht

Füge --no-open hinzu — das Relay gibt die Autorisierungs-URL aus, die du in einen Browser einfügen kannst.

Dynamische Client-Registrierung schlägt fehl

Der Registrierungs-Endpunkt des Servers ist eingeschränkt (z. B. durch Keycloaks Trusted-Hosts-Richtlinie). Falls es das OutSystems-Proxy ist, sollte das nicht passieren; andernfalls registriere einen Client selbst und übergib --client-id.

Etwas anderes

Öffne ein Issue mit dem vollständigen Fehlertext (alle Diagnosen gehen nach stderr — schwärze alle Tokens).

Nicht-Ziele (v1)

  • OS-Keychain-Token-Speicherung (derzeit Datei mit 0600-Berechtigungen)

  • Multi-Server-Aggregation / -Verwaltung (verwende dafür ein Gateway)

  • Vom Server initiierte Benachrichtigungs-Streams über die Durchreichung hinaus

  • Benutzerdefinierte CA-Flags

Lizenz

MIT

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Local stdio proxy for Uno MCP Gateway that enables MCP clients without OAuth support to securely connect to authenticated remote servers.
    1
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Bridges stdio-based LLM harnesses to OAuth-protected remote MCP servers via Streamable HTTP, handling PKCE browser login and token refresh automatically.
    9
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI clients like Claude to interact with Cartena tools via MCP, supporting remote OAuth or local stdio authentication.

View all related MCP servers

Related MCP Connectors

  • Access Kernel's cloud-based browsers and app actions via MCP (remote HTTP + OAuth).

  • StremAI MCP: shared memory for AI coding agents. Connected agents can recall. OAuth + local stdio.

  • Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/izambasiron/outsystems-mcp-relay'

If you have feedback or need assistance with the MCP directory API, please join our Discord server