Gemini CLI から Cloud Run にデプロイした MCP サーバに接続するベストプラクティス
10 月 8 日に Gemini CLI v0.8.0 がリリースされ、その中で IAP で保護された Cloud Run にデプロイされた MCP サーバへの接続がサポートされました。[1]
この新しい方法は、従来の Cloud Run プロキシを使う方法や OIDC ID トークンを使う方法のデメリットを解消しており、Gemini CLI から Cloud Run 上の MCP サーバに接続するベストプラクティスが確立されたと考えています。
今回はこの IAP for Cloud Run とサービスアカウントなりすましを使った方法を紹介します。
従来の方法とそのデメリット
従来の方法は Google Cloud のドキュメントにも記載されている以下の 2 つです。[2]
- Cloud Run プロキシを使う方法
- OIDC ID トークンを使う方法
なお Gemini CLI 以外の今回紹介する方法に対応していないクライアントを利用している場合は、引き続きこの 2 つのどちらかを採用してください。
Cloud Run プロキシを使う方法
この方法では Gemini CLI 起動前に、あらかじめローカルから Cloud Run へのプロキシを作成します。
gcloud run services proxy MCP_SERVER_NAME --region REGION --port=3000
settings.json
は以下のようになります。
{
"mcpServers": {
"someTools": {
"httpUrl": "http://127.0.0.1:3000/mcp"
}
}
}
この方法は Cloud Run proxy を利用しておりセキュリティ的に安全です。
また Cloud Run 側に接続のための設定などをする必要がなく、デプロイした MCP サーバをそのまま利用することができます。
デメリットとしては、Gemini CLI 起動前にコマンドを実行する必要があること、プロキシを作成したいポートが必ず空いているとは限らないためリポジトリのsettings.json
に記載してチームで共有しづらいことがあります。
OIDC ID トークンを使う方法
この方法では Gemini CLI 起動前に ID トークンを生成し、トークンを用いて Cloud Run で認証します。
export ID_TOKEN=$(gcloud auth print-identity-token)
settings.json
は以下のようになります。
{
"mcpServers": {
"someTools": {
"httpUrl": "https://MCP_SERVER_NAME.run.app/mcp",
"headers": {
"Authorization": "Bearer $ID_TOKEN"
}
}
}
}
この方法も Cloud Run プロキシと同様にセキュア、かつ Cloud Run 側で追加の設定は不要です。
また httpUrl
が固定のため、チーム内での共有にも向いています。
一方で引き続き Gemini CLI 起動前にコマンドを実行する必要があります。
また ID トークンは 1 時間の有効期限があり、有効期限が切れた場合は生成し直して Gemini CLI を再起動する必要があります。
ベストプラクティス
今回紹介する方法には以下のようなメリットがあります。
- IAP で認証するためセキュア
- Gemini CLI 起動前のコマンド実行は不要
-
httpUrl
は固定でチーム内で共有しやすい - トークンの管理は Gemini CLI がやってくれるので手動での再生成や再起動は不要
一方で、構築時には Google Cloud 側でいくつか設定が必要となります(コードの変更は不要です)。
設定方法はドキュメントにも記載がありますが[3]、分かりづらい部分もあるので以下で詳細に説明します。
0-a. Cloud Run への MCP サーバのデプロイ
新規に構築する場合はこちらになります。
今回サンプルとしてデプロイする MCP サーバのコードは以下になります。
動作確認できれば良いので本当に最低限。
from mcp.server.fastmcp import FastMCP
import os
port = int(os.getenv("PORT", 8080))
mcp = FastMCP("StatelessServer", stateless_http=True, host="0.0.0.0", port=port)
@mcp.tool()
def greet(name: str = "World") -> str:
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run(transport="streamable-http")
今回はソースコードからのデプロイをします。
そのために requirements.txt
と Procfile
を用意します。
annotated-types==0.7.0
anyio==4.11.0
attrs==25.4.0
certifi==2025.10.5
click==8.3.0
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
httpx-sse==0.4.2
idna==3.10
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
markdown-it-py==4.0.0
mcp==1.16.0
mdurl==0.1.2
pydantic==2.12.0
pydantic-core==2.41.1
pydantic-settings==2.11.0
pygments==2.19.2
python-dotenv==1.1.1
python-multipart==0.0.20
referencing==0.36.2
rich==14.1.0
rpds-py==0.27.1
shellingham==1.5.4
sniffio==1.3.1
sse-starlette==3.0.2
starlette==0.48.0
typer==0.19.2
typing-extensions==4.15.0
typing-inspection==0.4.2
uvicorn==0.37.0
web: python3 main.py
gcloud
コマンドでデプロイします。
オプションで IAP for Cloud Run を有効化しています。
gcloud beta run deploy cloud-run-mcp-server-sample --region asia-northeast1 --source . --no-allow-unauthenticated --iap
0-b. 既存の Cloud Run 上の MCP サーバの設定変更
既に従来の方法で構築済みの場合、移行は非常に簡単です。
サービスの「セキュリティ」タブで「Identity-Aware Proxy(IAP)」にチェックを入れ、保存します。
1. OAuth 2.0 クライアント ID の作成
以下の設定で OAuth 2.0 クライアント ID を作成します。
- アプリケーションの種類:ウェブアプリケーション
- 名前:お好み
- 承認済みのリダイレクト URI:
http://localhost:7777/oauth/callback
作成を押すとクライアント ID が表示されるのでコピーしておいてください。
2. クライアントをプログラマティックアクセス用のホワイトリストに追加
Gemini CLI のようなブラウザでないアプリケーションから IAP で保護されたリソースにアクセスするためには、クライアントをあらかじめ許可しておく必要があります。
iap-settings.yaml
を作成し、前の手順でコピーしておいたクライアント ID をペーストします。
access_settings:
oauth_settings:
programmatic_clients: [CLIENT_ID]
gcloud
コマンドを使って設定を適用します。
gcloud iap settings set iap-settings.yaml --project=PROJECT --resource-type=iap_web
3. サービスアカウントの作成
コンソールで SA を作成します。
権限の付与は不要です。
4. SA とユーザを IAP ポリシーに追加
前の手順で作成した SA と MCP サーバを利用するユーザを追加します。
設定はサービスの「セキュリティ」タブで「ポリシーの編集」を押します。
5. なりすましをするための権限の付与
MCP サーバを利用するユーザに「サービスアカウントトークン作成者」の権限を付与します。
以上で Google Cloud 側の設定は完了です。
6. Gemini CLI の設定
これまでの設定を settings.json
に反映させます。
-
httpUrl
:Cloud Run サービスの URL -
authProviderType
:"service_account_impersonation"
-
targetAudience
:クライアント ID -
targetServiceAccount
:サービスアカウント
{
"mcpServers": {
"myIapProtectedServer": {
"httpUrl": "https://my-iap-service.run.app/mcp",
"authProviderType": "service_account_impersonation",
"targetAudience": "YOUR_IAP_CLIENT_ID.apps.googleusercontent.com",
"targetServiceAccount": "your-sa@your-project.iam.gserviceaccount.com"
}
}
}
動作確認
起動時にエラーが出なければ OK です。
/mcp list
で Ready
と表示されます。
> /mcp list
Configured MCP servers:
🟢 greet - Ready (1 tool)
Tools:
- greet
💡 Tips:
- Use /mcp desc to show server and tool descriptions
- Use /mcp schema to show tool parameter schemas
- Use /mcp nodesc to hide descriptions
- Use /mcp auth <server-name> to authenticate with OAuth-enabled servers
- Press Ctrl+T to toggle tool descriptions on/off
> greet mcp toolを使って
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ greet (greet MCP Server) {"name":"mcp"} │
│ │
│ Hello, mcp! │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Hello, mcp!
Discussion