4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IAP保護された社内APIをMCP対応させる - リモートMCPサーバーによる実装

4
Last updated at Posted at 2025-12-05

はじめに

昨今、多様なサービスやプロダクトで MCP サーバーが公開され、AI Agent によるオペレーション自動化など、業務最適化への活用が進んでいます。
カスタム MCP サーバーを構築する際、認証をどのように実装するかは重要な検討事項の一つです。

本記事では、MCP サーバーの認証仕様を概説した後、弊社の既存環境(Google Cloud の IAP 保護下のAPI)へのリモートMCP サーバー導入を想定した実装検証を紹介します。

MCP サーバーの標準化された認可フロー

MCP の認証方式として、OAuth 2.0 および OAuth 2.1 に準拠した認可フローが定められています。

仕様では以下のように記載されています。

Authorization is OPTIONAL for MCP implementations

必須ではありませんが、HTTP 通信において認証を行う際の標準規格と位置づけられています。
以下は、公式サイトから引用した認証フローの図です。

Pasted image 20251205142642.png

この仕組みでは、クライアント(OAuth クライアントかつ MCP クライアント)は、事前に認可サーバーのメタデータを保持していなくても、MCP サーバーの URL から必要な情報を取得し、認可フローを実行できます。

また、OAuth クライアント ID は Dynamic Client Registration(DCR)によって ID プロバイダから動的に払い出される仕様となっており、事前のクライアント ID 発行は不要です。

なお、OAuth 2.1 は OAuth 2.0 に対して、Authorization Code Flow における PKCE の必須化や Implicit Flow の廃止など、セキュリティ強化のための制約が追加されたバージョンです。

上記フロー図はバージョン 2025-06-18 のドキュメントを参照していますが、執筆時点ではバージョン 2025-11-25 が最新となっています。

最新バージョンでは、DCR について代替仕様が公開され、DCR は後方互換性のために残された仕様となるなど、認可フローにも変更が加えられています。
本記事では、後段で紹介するサンプルコードの実装に合わせて、バージョン 2025-06-18 に基づいて説明します。

今回実現したいこと

弊社では、Google CloudのIdentity-Aware Proxy(IAP)で保護された社内 API が存在します。この API を MCP サーバー経由で利用可能にする際、認証をどのように実装するかが課題となります。

ローカル MCP サーバーとして実装する場合、MCP クライアントとMCP サーバー間の認証は不要ですが、代わりに IAP 保護された API への認証をローカル環境で処理する必要があります。
これには、サービスアカウントキーの管理や認証ロジックの実装といった複雑さが伴います。

本記事では、これらの課題を解決するため、リモート MCP サーバーとして実装する方法を採用します。
この方式では、MCP クライアント側はリモート MCP サーバーのURLを設定するだけで、ブラウザを経由したOAuth 2.0 / OAuth 2.1の認可コードフローにより MCP サーバーへの認証を完了できます。

前提となる環境と MCP サーバー構成図

本記事では、以下のような環境下において MCP サーバーを構築するケースを想定します。

対象は Google Cloud の IAP で保護された API で、API 側では IAP の認証結果である JWT トークンの検証を行い、email クレームによりアクセスユーザーを特定し、権限管理を行っています。

まず、MCP サーバーについては、認証仕様を満たすために IAP による保護は行いません。

また、Google Cloud の IAP への認証に必要な Bearer トークンは、OAuth 2.0 のフローで取得されるものとは異なり、ブラウザ以外のプログラムから認証する場合は、サービスアカウントを利用することが一般的です。

そのため、MCP サーバーと API サーバー間の認証についてはサービスアカウントで認証を行い、MCP サーバーを利用しているユーザーについては、別途ヘッダーを付与して API 側で判別できるようにしています。1

この構成では、MCP サーバーから API へのアクセスはインターネット経由で行われるため、MCP サーバーは任意の環境にホスティング可能です。

FastMCPによる MCP サーバーの実装

API は Python / FastAPI で実装されているため、MCP サーバーの実装には FastMCP を利用します。

FastMCP は、Python で MCP サーバーを実装するために十分な機能を備えているほか、各 ID プロバイダに対する個別実装や、FastAPI アプリからの MCP サーバー生成、FastAPI アプリへの MCP サーバーのマウントといった機能も提供しています。

事前準備として、Google Cloud コンソールから OAuth 2.0 のクライアント ID を発行しておく必要があります。以下を参考に対応します。2

以下のサンプルコードでは、既存の API のコードベースに MCP サーバーのエントリポイントを追加する形で、以下のようなディレクトリ構成を想定しています。

.
├── main_mcp.py  # MCPサーバーのエントリポイント
└── main.py      # APIサーバーのエントリポイント

また、ライブラリのバージョンは以下で確認しています。

fastmcp==2.13.1
main_mcp.py
from typing import Any

import httpx
from fastmcp import FastMCP
from fastmcp.server.auth.providers.google import GoogleProvider
from fastmcp.server.dependencies import get_access_token
from google.auth.transport.requests import Request
from google.oauth2 import id_token

from main import app


def auth_function(request: httpx.Request) -> httpx.Request:
    access_token = get_access_token()
    open_id_connect_token = id_token.fetch_id_token(
        Request(), client_id="YOUR_IAP_CLIENT_ID"
    )
    auth_headers = {
        # API側にMCPサーバーにアクセスしたユーザーを渡すためのヘッダー
        # 注: API側では呼び出し元がMCPサーバーのサービスアカウントからのリクエストであることを確認すること
        "X-MCP-USER": access_token.claims.get("email", ""),
        "Authorization": "Bearer {}".format(open_id_connect_token),
    }
    if auth_headers:
        request.headers.update(auth_headers)
    return request


auth_provider = GoogleProvider(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    base_url="YOUR_MCP_SERVER_BASE_URL",
    required_scopes=[
        "openid",
        "https://www.googleapis.com/auth/userinfo.email",
    ],
)

# authパラメータに関数を渡すと、httpxが自動的にFunctionAuthに変換してリクエストごとに認証ヘッダーを設定
httpx_client_kwargs: dict[str, Any] = {
    "auth": auth_function,
}

# FastMCP.from_fastapi() を使って既存のFastAPIアプリからFastMCPインスタンスを生成
mcp = FastMCP.from_fastapi(
    app=app,
    name="Sample MCP Server",
    httpx_client_kwargs=httpx_client_kwargs,
    auth=auth_provider,
)

# FastMCPのFastAPIアプリを取得
app = mcp.streamable_http_app()

このサンプルコードでは、既存の FastAPI の app インスタンスから MCP サーバーを自動生成しています。

内部的には OpenAPI スキーマが利用されるだけなので、専用で FastAPI の app インスタンスを生成してルーティングを登録することで、特定の API のみを MCP サーバーに対応させるといったカスタマイズも可能です。

API サーバーへの認証は、httpx_client_kwargs の auth パラメータに関数を指定することで実装しています。

MCP Inspectorによる動作確認

今回は MCP Inspector を利用して、構築した MCP サーバーに対して動作確認を行います。

$ npx @modelcontextprotocol/inspector

コマンドを実行すると、ブラウザで MCP Inspector が開きます。
以下のパラメータを指定したのち、Open Auth Settings → Quick OAuth Flow と操作すると、認可画面に遷移します。

Transport Type: Streamable HTTP
URL: MCPサーバーのURL(https://{ホスト名}/mcp)

Pasted image 20251205135400.png

Allow Access を押下し、Google ログイン後に MCP Inspector で Connect ボタンを押下することで、MCP サーバーへの接続が完了します。

Pasted image 20251205141214.png

MCP クライアント側の対応状況と回避策

認証については MCP クライアント側の仕様にも要件が定められていますが、MCP に対応した生成 AI ツールでも必ずしも対応が進んでいるわけではありません。

非対応の生成 AI ツールについては、 mcp-remote を利用することで、同様に認証を行うことができます。

ただし、このツールの README には以下の注意書きがあります。

Note: this is a working proof-of-concept but should be considered experimental.

このため、各種生成 AI ツールが正式対応するまでは、フィジビリティ検証や開発支援目的での利用にとどめ、ビジネス的な影響が大きい箇所では使用しないなどの判断が必要になりそうです。

おわりに

本記事では、MCP サーバーの認証方式の概要と、自社における活用例について紹介・検証してきました。

OAuth 2.0 に準拠した認証で MCP サーバーを運用するうえで有用な検証結果が得られた一方で、認証仕様や関連ツールのアップデートが頻繁であることや、生成 AI ツール側の対応がまだ十分に進んでいない点といった課題も見えてきました。

今後の動向を注視しながら、本番環境への導入を検討していければと思います。


そしてまだまだインティメート・マージャー アドベントカレンダーは続きます!

また、インティメート・マージャーでは、新卒から中途採用まで幅広く採用募集中です!
記事を読んで弊社に興味を持ってくれた方は、下記より採用情報をチェック!

  1. IAP ではなく、OAuth2.0 のリソースサーバーに相当する API であれば MCP サーバーで取得したアクセストークンをそのまま利用して API コールすることも検討できそうです

  2. Google は Dynamic Client Registration (DCR) に対応していないため、MCP サーバー上に OAuthProxy を構築した上で、動的なクライアントIDの代わりに事前に作成されたクライアントIDを返却することにより、MCP サーバーの認可フローを実現しています

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?