メインコンテンツにスキップ

MCP サーバーを Casdoor MCP ゲートウェイの背後に配置する(エンドツーエンド)

このガイドでは完全な例を実演します。企業は 1 つの MCP サーバーを従業員に公開し、従業員は ChatGPT、Claude、Cursor、VS Code からそれを使用します。Casdoor はサーバーの前面にあるゲートウェイであり、ユーザーを認証する認可サーバーでもあります。MCP サーバー自体には OAuth 2.0 のコードは不要です。


学習目標​

  • MCP クライアントが登録しサインインできるように組織を準備します。
  • Casdoor に MCP サーバーを登録し、誰がそれを使用でき、どのツールを利用可能かを決定します。
  • 4 つの一般的な MCP クライアントに接続します。
  • 1 つの Casdoor インスタンスから複数の組織に対応します。
  • アクセスの確認、監査、および取り消しを行います。

必要なもの​

  • HTTPS 経由でインターネットから到達可能な Casdoor インスタンス(例:https://auth.example.com)。ChatGPT および Claude のカスタムコネクタはクラウドからこれを呼び出します。
  • Streamable HTTP トランスポートに対応した MCP サーバー(例:https://tickets.example.com/mcp)、必要に応じて静的ベアラートークンで保護されます
  • Casdoor 管理コンソールへのグローバル管理者アクセス権

例​

Acme はチケットシステム用の MCP サーバーを運用しています。Acme は以下を望んでいます:

  • 従業員は Acme アカウントでサインインし、Casdoor で既に設定済みのサインイン方法を利用します。
  • サポートチームのみがサーバーを使用できます。
  • AI クライアントを通じてツール delete_ticket を呼び出すことはできません。
  • サーバー自身の API トークンは Casdoor の外に出ません。
  • 管理者は各クライアントを確認し、取り消すことができます。

ステップ 1: 組織の準備​

  1. Casdoor 管理コンソールで、User Management > Organizations に移動し、acme を開きます。
  2. Use organization issuer をオンにします。これにより、組織は独自の認可サーバーとなり、発行者は https://auth.example.com/orgs/acme、ディスカバリードキュメントは https://auth.example.com/.well-known/oauth-authorization-server/orgs/acme になります。これを見つける MCP クライアントは acme に登録され、acme のサインインページでユーザーを認証します。
  3. Enable dynamic client registration をオンにします。これにより、クライアントはクライアント ID メタデータドキュメント(Claude、VS Code、ChatGPT)で自己識別するか、自己登録(Cursor、古いクライアント)できるようになります。このスイッチを変更できるのはグローバル管理者のみです。
  4. 組織を保存します。

Use organization issuer なしの場合、ゲートウェイは Casdoor のグローバル発行者を認可サーバーとして指定し、クライアントは built-in に登録されます。built-in 以外のすべての組織で MCP サーバーを公開する場合は、これをオンにしてください。

ステップ 2: 誰がサーバーを使用できるかの決定​

ゲートウェイは、サーバーの組織のユーザーのうち、サーバーのアプリケーションにサインインできるユーザーを受け入れます。

  1. Identity > Applications に移動し、acme にアプリケーションを追加します(例:app-tickets)。リダイレクト URL は不要です。MCP クライアントはこれにサインインせず、アクセスルールを保持するだけです。
  2. サポートチームのみを受け入れるには、Authorization > Permissions に移動し、acme に権限を追加します:
    • Resource type: Application
    • Resources: app-tickets
    • Groups または Roles: サポートチーム
    • Actions: Read, Effect: Allow

アプリケーションに対する権限がなくても、acme のすべてのユーザーはサーバーを使用できます。acme の管理者とグローバル管理者は常に使用できます。

ステップ 3: MCP サーバーの登録​

  1. LLM AI > MCP Servers に移動し、acme でサーバーを追加します:

    フィールド値
    Nametickets
    URLhttps://tickets.example.com/mcp
    Applicationapp-tickets
    Access tokenチケットサーバーが必要とする場合、その API トークン
  2. サーバーを保存し、Tool の下にある Sync を選択します。Casdoor はサーバーのツールリストを取得します。

  3. delete_ticket をブロックして保存します。ゲートウェイは、ブロックされたツールまたはリストにないツールへの呼び出しに対してエラーを返し、転送しません。

  4. Base URL をコピーします: https://auth.example.com/api/server/acme/tickets。これは、ユーザーが MCP クライアントに追加する URL です。

ゲートウェイは、各リクエストから Cookie ヘッダーとユーザーの Authorization ヘッダーを削除し、代わりにサーバーの Access token を送信します。Casdoor は API レスポンスでトークンを返しません。

注

built-in 以外の組織のサーバーの場合、URL は公開インターネットアドレスである必要があります。ゲートウェイはテナントのためにプライベートアドレスやループバックアドレスへ到達することを拒否します。内部ネットワーク上の MCP サーバーを公開するには、built-in に登録してください。

ステップ 4: 発見チェーンの確認​

すべての MCP クライアントは同じチェーンに従います。クライアントを接続する前に curl を使用して確認してください:

curl -i -X POST https://auth.example.com/api/server/acme/tickets

Casdoor は HTTP 401 を返し、このサーバーの保護されたリソースメタデータを指定します:

WWW-Authenticate: Bearer realm="casdoor", resource_metadata="https://auth.example.com/.well-known/oauth-protected-resource/api/server/acme/tickets"
curl https://auth.example.com/.well-known/oauth-protected-resource/api/server/acme/tickets
{
"resource": "https://auth.example.com/api/server/acme/tickets",
"authorization_servers": ["https://auth.example.com/orgs/acme"],
"bearer_methods_supported": ["header"],
"scopes_supported": ["openid", "profile", "email", "offline_access"]
}
curl https://auth.example.com/.well-known/oauth-authorization-server/orgs/acme

このドキュメントでは、次を確認します:

  • issuer は https://auth.example.com/orgs/acme であり、authorization_servers と同じ値です。
  • client_id_metadata_document_supported が true であり、registration_endpoint が ?organization=acme で終わっています。
  • token_endpoint_auth_methods_supported に none が含まれており、code_challenge_methods_supported に S256 が含まれています。

ステップ 5: クライアントの接続​

各ユーザーはゲートウェイ URL をクライアントに追加し、Acme アカウントでサインインします。

クライアントサーバーを追加する場所自己識別方法ガイド
ChatGPTPlugins > + > Add custom MCP serverCIMD https://chatgpt.com/oauth/client.jsonConnect ChatGPT
Claude Desktop, claude.aiCustomize > Connectors > Add custom connectorCIMD https://claude.ai/oauth/mcp-oauth-client-metadataConnect Claude
Claude Codeclaude mcp add --transport http tickets <url>CIMD https://claude.ai/oauth/claude-code-client-metadataConnect Claude
Cursor~/.cursor/mcp.jsonDCRConnect Cursor
VS Code.vscode/mcp.jsonCIMD https://vscode.dev/oauth/client-metadata.jsonConnect VS Code

例えば、Cursor では:

{
"mcpServers": {
"tickets": {
"url": "https://auth.example.com/api/server/acme/tickets"
}
}
}

VS Code では:

{
"servers": {
"tickets": {
"type": "http",
"url": "https://auth.example.com/api/server/acme/tickets"
}
}
}

クライアント ID メタデータドキュメントを使用するクライアントは、Casdoor に 1 つのアプリケーションが作成され、その URL がクライアント ID となり、タグは cimd、名前は cimd_ で始まります。自己登録するクライアントは、登録ごとに 1 つのアプリケーションが作成され、タグは dcr です。クライアント用のアプリケーションを手動で作成する必要はありません。

サーバーを保護するもの​

チェック項目場所それ以外の場合の動作
トークンは acme のユーザーのものであるゲートウェイHTTP 401
ユーザーは app-tickets にサインインできるゲートウェイHTTP 401
トークンはこのサーバー向けに発行された (RFC 8707)ゲートウェイHTTP 401: "The access token is for another resource"
ツールはリストに含まれており許可されているゲートウェイJSON-RPC エラー、呼び出しは転送されない
クライアントは自己登録したクライアントであるすべての APIそのトークンはサインインフロー、/api/userinfo、/api/mcp、および /api/server/* のみを呼び出すことができ、管理 API は呼び出せない

クライアントは resource=https://auth.example.com/api/server/acme/tickets を使用してトークンをリクエストし、Casdoor はその URL を aud クレームに入れます。他の MCP サーバー(同じ組織であっても)向けのトークンはここでは機能しないため、悪意のあるサーバーが受信したトークンを再生することはできません。

複数の組織を提供する​

1つのCasdoorインスタンスで、SaaSの顧客など、多くの組織向けにMCPサーバーを公開できます。各組織に対して手順1から3を繰り返してください。その後:

  • 各組織には独自のイシューア、サインインページ、ユーザー、権限があります。globex のユーザーは acme のページでサインインできず、acme のサーバーを使用することもできません。
  • ChatGPT、Claude、VS CodeのクライアントIDメタデータドキュメントにはそれぞれ1つのURLがあり、すべての組織で使用されます。Casdoorは built-in にそのURLごとの共有アプリケーションを保持し、ユーザーがサインインする組織のアプリケーションとして提供します。これらのクライアントを受け入れるために、各組織では依然として Enable dynamic client registration を有効にする必要があります。
  • トークンにはユーザーの組織のイシューアが含まれており、リフレッシュ後も同様です。
  • 自己登録を行うクライアント(DCR)は、登録エンドポイントの organization パラメータを通じて、ディスカバリドキュメントの組織に登録されます。

確認、監査、失効​

  • Clients: Identity > Applications に、タグ cimd および dcr を持つクライアントが一覧表示されます。dcr_ アプリケーションを削除すると、登録が解除されます。
  • Tokens: Auditing > Tokens に、ユーザー、アプリケーション、スコープ、リソースを含む各トークンが一覧表示されます。トークンを削除すると、クライアントへのアクセスが直ちに遮断されます。
  • Users: ユーザーを禁止すると、そのユーザーのトークンは次のリクエスト時にゲートウェイで機能しなくなります。
  • Tools: サーバーの編集ページでツールをブロックします。変更は次の呼び出し時に反映されます。

エンタープライズユーザーがブラウザをスキップできるようにする​

組織の従業員がOktaなどのエンタープライズIDプロバイダーを通じてサインインする場合、Enterprise-Managed Authorizationをサポートするクライアント(Claude TeamおよびEnterprise)は、ブラウザでのサインインなしでゲートウェイトークンを取得できます。IDプロバイダーがID-JAGを発行し、Casdoorがそれをアクセストークンと交換します。詳細については、Enterprise-managed authorizationを参照してください。

トラブルシューティング​

サインイン後にゲートウェイが401を返す場合​

  • サーバーに Application が設定されていません。これがない場合、管理者のみがサーバーを使用できます。アプリケーションを選択してください。詳細は Step 2 を参照してください。
  • アプリケーションの権限によりユーザーが除外されています。
  • ユーザーがサーバーとは別の組織に属しています。
  • クライアントが別のリソース用のトークンを要求しました。トークンの aud クレームを確認してください。これはゲートウェイURLである必要があります。

クライアントが誤った組織でユーザーをサインインさせている場合​

Use organization issuer がオフになっているため、保護されたリソースメタデータはグローバルなイシューアを指定しています。これをオンにし、クライアントを再接続してください。

"client ID metadata documents are not accepted"​

組織に対して Enable dynamic client registration がオフになっています。また、Casdoorはインターネット経由でクライアントのドキュメントURLに到達できる必要があります。

ゲートウェイが502を返す場合​

Casdoorがサーバーの URL に到達できません。URLを確認し、built-in 以外の組織の場合は、パブリックアドレスであることを確認してください。

関連項目​