Skip to main content
Glama

image-gen-mcp

Google の Gemini ネイティブ画像モデル("Nano Banana")で画像を生成する MCP サーバー。Streamable HTTP で提供されます。

ツールは generate_image の 1 つだけ。どこにも状態がなく、独自の認証もありません。本番では mcp-oauth-proxy の背後でバックエンドとして動作し、cloudrun-mcp-deployment によってデプロイされます。

DESIGN.md ではこのような構成にした理由を、このファイルではその実行方法を説明します。

クイックスタート(ローカル、トークン認証)

uv sync
export GEMINI_API_KEY="…"                       # from Google AI Studio
export IMAGE_MCP_TOKEN="$(openssl rand -base64 32)"
uv run python -m image_gen_mcp

http://127.0.0.1:8080/mcp に Authorization: Bearer $IMAGE_MCP_TOKEN を付けてクライアントを接続します。Claude Code の場合:

claude mcp add --transport http image-gen http://127.0.0.1:8080/mcp \
  --header "Authorization: Bearer $IMAGE_MCP_TOKEN"

Related MCP server: Imagen MCP Server

ツール

generate_image(prompt, aspect_ratio="1:1", image_size="1K", model=None)

パラメータ

値

prompt

自由テキスト、IMAGE_MCP_MAX_PROMPT 文字まで

aspect_ratio

1:1 16:9 9:16 4:3 3:4 3:2 2:3 21:9 4:5 5:4

image_size

1K 2K 4K — 2K/4K には高性能なモデル と バケットが必要

model

オプション。IMAGE_MCP_ALLOWED_MODELS に含まれている必要があります

IMAGE_MCP_INLINE_MAX_BYTES(デフォルト 1.5 MB)以下の画像はインラインで返され、チャット内に表示されます。それより大きい画像は Cloud Storage にアップロードされ、署名付き URL として返されます。構造化出力には、実際のピクセル寸法、使用されたモデル、使用された配信経路が常に報告されます。

モデル / 解像度の対応

モデル

1K

2K

4K

gemini-2.5-flash-image(デフォルト)

✅

—

—

gemini-3-pro-image-preview / gemini-3-pro-image

✅

✅

✅

gemini-3.1-flash-lite-image

✅

✅

✅

サポートされていない組み合わせは、30 秒のラウンドトリップの後ではなく、ツールの境界で数ミリ秒以内に拒否され、サポートされているものを明示するメッセージが返されます。

設定

すべては環境変数から取得します。注釈付きの一覧は .env.example を参照してください。基本は次のとおりです。

変数

必須

目的

GEMINI_API_KEY

必須

Google AI Studio のキー

IMAGE_MCP_TOKEN

プロキシを使わない場合

静的ベアラートークン

IMAGE_MCP_MODEL

デフォルトモデル

IMAGE_MCP_ALLOWED_MODELS

呼び出し元が選択できるモデル

IMAGE_MCP_TRUST_PROXY_HEADERS

プロキシ配下

X-Auth-* から ID を取得

ALLOWED_EMAILS

プロキシの許可リストを任意に絞る

IMAGE_MCP_GCS_BUCKET

2K/4K 用

大きすぎる画像用のバケット

サーバーは、誤設定のまま動作するのではなく起動を拒否します。API キーがないこと、および認証の境界が一切ないこと(静的トークンもプロキシモードもないこと)は、どちらも起動失敗になります。

認証

2 つの形があり、どちらもない場合はサーバーは起動を拒否します。

プロキシ経由(本番)。 IMAGE_MCP_TRUST_PROXY_HEADERS=1 を設定します。プロキシはユーザーを Google に対して認証し、許可リストを適用し、クライアントの Authorization ヘッダーを取り除いて、ID を X-Auth-Email / X-Auth-Subject / X-Auth-Scope として転送します。このサーバーはこれらを読み取り、自身のトークンは必要ありません。X-Auth-Email のないリクエストは 401 になります。

ヘッダーを信頼するのが安全なのは、そのプロセスに他がアクセスできない場合だけです。Cloud Run のマルチコンテナ構成では、バックエンドはイングレスポートを宣言しないため、ソケットを開けることができるのは同じインスタンス内のプロキシと起動プローバーのみです。ルーティング可能なポートで有効にしないでください。

ALLOWED_EMAILS はここでは省略可能で、プロキシの許可リストを 狭めます。プロキシがドメイン全体を許可しているが、画像生成にかかるコストを一部の人だけに請求したい場合に便利です。未設定の場合は「プロキシが許可したすべての人」を意味します。

トークン(ローカル、Claude Code)。 IMAGE_MCP_TRUST_PROXY_HEADERS は設定せず、IMAGE_MCP_TOKEN を設定します。呼び出し元は Authorization: Bearer <token> を送信します。X-Auth-* ヘッダーは完全に無視されます。プロキシがない場合、それらは信頼できないリクエストデータにすぎないからです。

サーバーは OAuth を終端せず、/authorize、/token、/register エンドポイントも持ちません。GOOGLE_OAUTH_CLIENT_ID または _SECRET を設定すると、静かな no-op ではなく起動エラーになります。これらはプロキシ側で設定するものです。

イメージのビルド

.github/workflows/build.yml はテストを実行し、イメージをビルドして GitHub Container Registry に公開します。デプロイは行いません。デプロイは別のワークフローまたはリポジトリが担当します。

イベント

テスト

ビルド

プッシュ

プルリクエスト

✅

✅

—

main へのプッシュ

✅

✅

latest, sha-<full-sha>

タグ v*

✅

✅

1.2.3, 1.2, sha-<full-sha>

ghcr.io/ramzpat/image-gen-mcp として公開されます。設定は不要です。ワークフローは組み込みの GITHUB_TOKEN で認証します。

デプロイワークフローから利用する

タグではなくダイジェストでデプロイします。 :latest のような可変タグの前にある pull-through キャッシュは、以前のイメージをそのまま提供してしまいます。ダイジェストは古くなることがありません。各実行はダイジェストをジョブサマリーに出力し、ビルドとデプロイを 1 つのパイプラインで行いたい場合はこのワークフローを呼び出せます。

jobs:
  build:
    uses: ramzpat/image-gen-mcp/.github/workflows/build.yml@main
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "deploying ${{ needs.build.outputs.image }}@${{ needs.build.outputs.digest }}"

別のリポジトリからは、デプロイ時にダイジェストを解決してください。

DIGEST=$(docker buildx imagetools inspect \
  ghcr.io/ramzpat/image-gen-mcp:latest --format '{{.Manifest.Digest}}')

GHCR パッケージはデフォルトではプライベートです。別のリポジトリのデプロイジョブには、read:packages 権限を持つ PAT か、GitHub のパッケージ設定でパッケージを公開に設定するかのどちらかが必要です。

デプロイ

cloudrun-mcp-deployment(.github/workflows/deploy-image-gen-mcp.yml)によってデプロイされます。このイメージを mcp-oauth-proxy を前面に置いた Cloud Run マルチコンテナサービスのバックエンドコンテナとして実行します。そのリポジトリが GCP プロジェクト、リージョン、許可リスト、シークレットを管理し、このリポジトリはイメージを公開するだけです。

そのデプロイがこのコンテナに設定するものは次のとおりです。

PORT / HOST

8000 / 0.0.0.0(共有デプロイアクションによって設定)

IMAGE_MCP_TRUST_PROXY_HEADERS

1

GEMINI_API_KEY

サービスの GitHub Environment シークレットから

エントリポイント

/app/.venv/bin/python -m image_gen_mcp

HOST=0.0.0.0 はループバックではなく必要であり、漏えいではありません。Cloud Run の起動プローバーはコンテナのネットワーク名前空間の外で実行されるため、ループバック専用ソケットには到達できないからです。--port(proxy)を宣言したコンテナだけがイングレスを受け取るので、バックエンドはインスタンス外部からは到達できないままです。

2K/4K 用の Cloud Storage

gcloud storage buckets create gs://BUCKET --uniform-bucket-level-access
gcloud storage buckets update gs://BUCKET \
  --lifecycle-file=<(echo '{"rule":[{"action":{"type":"Delete"},"condition":{"age":30}}]}')

# The runtime service account signs URLs through the IAM Credentials API,
# because it has no private key file. It needs this role *on itself*:
gcloud iam service-accounts add-iam-policy-binding RUNTIME_SA \
  --member="serviceAccount:RUNTIME_SA" --role=roles/iam.serviceAccountTokenCreator
gcloud storage buckets add-iam-policy-binding gs://BUCKET \
  --member="serviceAccount:RUNTIME_SA" --role=roles/storage.objectAdmin

署名付き URL が壊れる最も一般的な原因は、serviceAccountTokenCreator のバインディングを省略することです。

テスト

uv run pytest -q

57 件のテスト: 起動時ガード、両方の形状での ID 解決(プロキシヘッダーと静的トークン。それぞれが相手の認証情報を無視することを含む)、および実際の MCP クライアントを uvicorn に対して実際の HTTP で動かすエンドツーエンドのスモークテスト。トークンモードとプロキシ経由の本番形状の両方で行います。

コスト

許可されたすべてのユーザーが 1 つの API キーを使用します。実際に効果が高い順の制御: --max-instances、IMAGE_MCP_MAX_CONCURRENCY、GCP の課金予算アラート、IMAGE_MCP_RATE_PER_HOUR。レート制限はインスタンスごとにカウントされるため、実際の上限は IMAGE_MCP_RATE_PER_HOUR × --max-instances です。

Related MCP Connectors

Related MCP Servers