outsystems-mcp-relay
{"type": "text"}# outsystems-mcp-relay
軽量で汎用的な stdio → リモート MCP リレー。OAuth 対応、さらにリモートサーバーの公開 OAuth メタデータが認可応答と一致しない場合の RFC 9207 発行者オーバーライド機能を備えています。ランタイム依存関係ゼロ。単一ファイル。
stdio (your MCP client) ⇄ outsystems-mcp-relay ⇄ remote MCP server (Streamable HTTP)なぜこれが存在するのか
一部のリモート MCP デプロイメントは Keycloak の前段にリバースプロキシを置いています(OutSystems Developer Cloud MCP ゲートウェイもその一つ)。それらは issuer がプロキシ URL(例: https://<tenant>/mcp)である OAuth メタデータを公開しますが、認可サーバーは認可応答の iss パラメータに実際の発行者(例: https://<tenant>/auth/realms/<realm>)をスタンプします。
RFC 9207 準拠のクライアントはその不一致を拒否しなければならないため、Claude Code、pi、Cursor、Codex など、あらゆるハーネスで OAuth ログインが失敗します。このリレーは、他のすべての OAuth チェックを厳格に保ちながら、iss を実際のバックエンド発行者に対して検証できるようにします。通常のサーバーに対しては、単なるリレーとして動作します。
Related MCP server: mcp-auth-proxy
いつこれを使うべきか
まず公式の直接接続を試してください — ハーネスをリモート MCP URL に直接向け、リレーを挟まないでください。上記の RFC 9207 発行者不一致エラーで失敗した場合にのみ、このリレーに手を伸ばしてください。
これは、そのサーバー側のバグを回避するためだけに存在します。バグが存在しない場合、公式パスより優れたことは何もありません。したがって、OutSystems がテナント全体で修正した場合、またはテナントがそもそもこの問題に遭遇しなかった場合は、リレーをやめて直接接続してください。リレーは、そのような場合にそれを通知します。ログイン成功時に、発行者補正が実際に必要だったかどうかを確認し、不要だった場合は stderr にその旨のメモを出力します。「まだ必要か」のレビューを待つ必要はありません。そのメモが表示されたら、すぐに公式の直接接続に戻してください。
インストール
Node.js ≥ 20 が必要です。依存関係なし — ファイルだけです。
npm install -g outsystems-mcp-relay # recommended
# or, without a global install:
npx outsystems-mcp-relay <remote-url> ...このリポジトリをクローンする必要はありません。 npm からインストールするか(または npx を使用)、それで完了です。ソース(単一の ~500 行のファイル)を監査するため、または貢献する場合にのみクローンしてください。
使い方
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一般的な例(通常のリモートサーバー)
// mcp.json
{
"mcpServers": {
"my-remote": {
"command": "outsystems-mcp-relay",
"args": ["https://api.example.com/mcp"]
}
}
}OutSystems の例(発行者不一致)
{
"mcpServers": {
"outsystems": {
"command": "outsystems-mcp-relay",
"args": ["https://<tenant>.outsystems.dev/mcp"]
}
}
}--expected-issuer は不要です — リレーは認可リダイレクト(Keycloak レルム設定)から実際の認可サーバー発行者を自動検出します。自動検出が失敗した場合(Keycloak 以外のサーバー)にのみ、--expected-issuer https://<tenant>.outsystems.dev/auth/realms/<realm-id> を追加してください。OAuth エラーにはレルムが表示されます — その受信値が使用する値です。自動検出は、発行者がレルム自身のメタデータ(オリジン許可リスト経由で到達可能)によって確認された場合にのみ、クロスオリジンの候補を採用します。真に別の IdP ホストの場合は、--expected-issuer(または事前に許可リストに追加する --as-metadata-url)を渡してください。
最初の呼び出しで、リレーはサインイン用のブラウザを開きます(--no-open で URL を表示)。トークンはキャッシュされ、自動的に更新されます。
AI アシスタント経由でインストール(これを貼り付け)
Claude Code、pi、Cursor、または任意の AI ハーネスに貼り付け:
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 クイックスタート(OutSystems 発行者不一致)
表示されるエラーは次のようになります:
Issuer mismatch in authorization response (RFC 9207):
expected "https://<tenant>.outsystems.dev/mcp",
received "https://<tenant>.outsystems.dev/auth/realms/<realm-id>"ターミナルで(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その後、Claude Code を再起動します。最初の OutSystems ツール呼び出しで、リレーはサインイン用のブラウザを開きます(URL を貼り付けたい場合は --no-open を追加)。トークンはキャッシュされるため、以降のセッションではサインインがスキップされます。/mcp(サーバーが接続されているはず)と簡単な「環境一覧」で確認してください。
レルム発行者を探す必要はありません。 リレーは認可リダイレクトから自動検出します。自動検出ができない場合(Keycloak 以外のサーバー)、エラーメッセージに表示されます。エラー内の受信値が
--expected-issuerの値です。
仕組み
プロトコル非依存のパススルー: stdin から改行区切りの JSON-RPC を読み取り、各フレームをそのままリモートサーバーに POST し、JSON-RPC 応答を stdout に書き込みます。ツールのセマンティクスはここにはありません — ツール、リソース、プロンプト、何でも動作します。
Streamable HTTP の詳細を処理:
Mcp-Session-Idエコー、直接 JSON 応答、202/text/event-stream応答(SSE 再アセンブリ)。OAuth: 認可サーバーのメタデータを検出し、パブリッククライアント(PKCE S256)を動的登録し、ブラウザを開き、
stateとissを検証し、コードを交換し、401 でトークンを更新します。--expected-issuerはissが検証される発行者を設定します — プロキシ/Keycloak 不一致の修正です。リクエストは直列化されます(stdout にインターリーブされた応答はありません)。
セキュリティ
RFC 9207 を強制:
issは、認可サーバーが実際に送信する場合にのみ検証されます(不在 = AS が RFC 9207 を実装していない、チェックなし。存在 = 期待される発行者との厳密な文字列一致)。--expected-issuerは異なる期待値を選択します — 検証を無効にすることはありません。オリジン許可リスト: リレーは設定されたリモートオリジン(および明示的に指定された
--as-metadata-url)にのみ接続します。リダイレクトは手動で追跡され、すべてのホップが許可リストに登録されます(307/308 はリクエストボディを保持。301/302/303 は HTTP セマンティクスに従って GET にダウングレード)。また、リダイレクトがオリジンを変更する場合、Authorization/Cookieは削除されます(ネイティブ fetch と一致)。SSRF はありません。PKCE S256 + ランダムな
state(検証済み)+ エフェメラルポート上の localhost のみのコールバックサーバー。シークレットをログに記録しない: トークンと認可コードが出力に表示されることはありません(すべての診断は stderr に。stdout はプロトコルメッセージのみ)。
トークンは
~/.mcp-auth/outsystems-mcp-relay-<sha1(url)>.jsonに0600パーミッションで保存されます — エコシステムの慣例(mcp-remoteと同じストア形状)。OS キーチェーンストレージは計画中の拡張です。非目標を参照してください。
テスト
npm test # mock-server protocol test (passthrough, session-id, SSE, 401)
npm run test:e2e -- <remote-url> --expected-issuer <issuer> # real-tenant round tripトラブルシューティング
症状 | 修正 |
| 通常は自動検出がフラグなしで処理します。できない場合は、受信 URL を |
長時間アイドル後の | キャッシュされたトークンの有効期限が切れ、更新に失敗しました。 |
ブラウザが開かない |
|
動的クライアント登録が失敗する | サーバーの登録エンドポイントが制限されています(例: Keycloak の Trusted-Hosts ポリシー)。OutSystems プロキシの場合は発生しないはずです。それ以外の場合は、自分でクライアントを登録し、 |
その他 | 完全なエラーテキスト(すべての診断は stderr に出力されます — トークンは編集してください)を添えて issue を開いてください |
非目標(v1)
OS キーチェーントークンストレージ(当面は 0600 パーミッションのファイル)
マルチサーバー集約/管理(その場合はゲートウェイを使用)
パススルーを超えたサーバー開始通知ストリーミング
カスタム CA フラグ
ライセンス
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
- QuallaaOAuthcom.quallaa
Talk to your public-facing AI from any MCP client — Claude, ChatGPT, Cursor, Cline, Windsurf.
Hosted OAuth MCP at https://www.taskade.com/mcp, or local @taskade/mcp-server.
Enable secure connectivity between Sentry issues and debugging data, and LLM clients, using a Model Context Protocol (MCP) server.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Related MCP Servers
- AlicenseAqualityCmaintenanceLocal stdio proxy for Uno MCP Gateway that enables MCP clients without OAuth support to securely connect to authenticated remote servers.821 PyPI1MIT
- FlicenseNot gradedqualityDmaintenanceBridges stdio-based LLM harnesses to OAuth-protected remote MCP servers via Streamable HTTP, handling PKCE browser login and token refresh automatically.5 npm-
- AlicenseNot gradedqualityAmaintenanceBridge that lets stdio-only MCP clients connect to remote MCP servers with OAuth and other auth support, enabling local clients to use remote, authorized MCP servers.19 npm54MIT
- FlicenseNot gradedqualityCmaintenanceEnables local MCP clients to access tools from a remote FastMCP server over stdio, handling OAuth authentication and Streamable HTTP communication.-