Skip to main content
Glama

image-gen-mcp

MCP-сервер, который генерирует изображения с помощью нативных моделей генерации изображений Google Gemini («Nano Banana»), предоставляемых через Streamable HTTP.

Один инструмент — generate_image. Никакого состояния, никакой собственной аутентификации: в продакшене он работает как бэкенд за 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 нужны подходящая модель и bucket

model

необязательный; должен быть в IMAGE_MCP_ALLOWED_MODELS

Изображения размером не больше IMAGE_MCP_INLINE_MAX_BYTES (по умолчанию 1.5 МБ) возвращаются инлайн и отображаются в чате. Более крупные загружаются в 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

если не за прокси

статический bearer-токен

IMAGE_MCP_MODEL

модель по умолчанию

IMAGE_MCP_ALLOWED_MODELS

модели, которые может выбрать вызывающий

IMAGE_MCP_TRUST_PROXY_HEADERS

за прокси

брать личность из X-Auth-*

ALLOWED_EMAILS

опциональное сужение списка разрешённых прокси

IMAGE_MCP_GCS_BUCKET

для 2K/4K

bucket для изображений большего размера

Сервер откажется запускаться, а не работать с некорректными настройками: отсутствие API-ключа и отсутствие аутентификационной границы вообще (ни статического токена, ни прокси-режима) являются ошибками запуска.

Аутентификация

Есть два режима, и без любого поля сервер не запускается.

За прокси (продакшн). Установите IMAGE_MCP_TRUST_PROXY_HEADERS=1. Прокси аутентифицирует пользователя через Google, применяет свой allowlist, снимает заголовок Authorization клиента и передаёт личность в заголовках X-Auth-Email / X-Auth-Subject / X-Auth-Scope. Сервер читает эти заголовки и не требует собственного токена — запрос без X-Auth-Email получает 401.

Доверять заголовкам безопасно только потому, что до процесса больше никто не может достучаться: в многоконтейнерной схеме Cloud Run бэкенд не объявляет входящий порт, поэтому открыть сокет к нему могут только прокси в том же экземпляре и стартовый пробер. Никогда не включайте это на маршрутизируемом порту.

ALLOWED_EMAILS здесь необязателен и сужает allowlist прокси — это полезно, когда прокси допускает целый домен, а генерация изображений должна тратить средства только на нескольких человека. Если не установлено — «кто вошёл через прокси».

Токен (локально, 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. Деплой он не выполняет — развёртывание делает отдельный workflow или репозитория.

Событие

Тест

Сборка

Публикация

pull request

✅

✅

—

push в main

✅

✅

latest, sha-<full-sha>

тег v*

✅

✅

1.2.3, 1.2, sha-<full-sha>

Публикуется как ghcr.io/ramzpat/image-gen-mcp. Настраивать ничего не нужно: workflow аутентифицируется встроенным GITHUB_TOKEN.

Использование в workflow деплоя

Деплой по digest, а не по тегу. Pull-through cache перед изменяемым тегом типа :latest с радостью выдаст старый образ; digest не может появиться на свет. Каждое выполнение печатает digest в возившую job summary, а workflow вызывавший — если нужно собрать и задеплоить в едином конвейере:

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 и задеплой, в шаге:

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

Пакет GHCR по умолчанию приватный. Задание деплоя в другом репозитории требует либо PAT с правами read:packages, либо перевода пакета в публичный в настройках пакета GitHub.

Деплой

Развёрнут с помощью cloudrun-mcp-deployment (.github/workflows/deploy-image-gen-mcp.yml), которая запускает этот образ как контейнер backend многоконтейнерного сервиса Cloud Run с mcp-oauth-proxy перед ним. Там находятся проект GCP, регион, allowlist и секреты; здесь только публикация.

Что эта деплой задаёт в этом контейнере:

PORT / HOST

8000 / 0.0.0.0 (задаётся общим workflow деплоя)

IMAGE_MCP_TRUST_PROXY_HEADERS

1

GEMINI_API_KEY

из GitHub Environment secret этого сервиса

entrypoint

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

HOST=0.0.0.0 вместо loopback — это требование, а не утечка: стартовый пробер Cloud Run работает но сетевом неймспейсе контейнера и не может достучаться до socket на loopback. Входящих трафик получает только контейнер, объявивший --port (прокси), поэтому backend остаётся недоступным извне экземпляра.

Cloud Storage для 2K/4K

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 тестов: стартовые проверки, разрешение идентичности в обеих формах (заголовки прокси, статический токен, и каждая форма игнорирует другой атрибут), валидация инструмента и доставка, а также сквозные дымовые тесты, прогоняющие настоящий MCP-клиент по настоящему HTTP к uvicorn — в токен-режиме и в продакшн-форме с прокси.

Стоимость

Каждый разрешённый (allowlisted) пользователь использует один общий API-ключ. Регуляторы в порядке реального эффекта: --max-instances, IMAGE_MCP_MAX_CONCURRENCY, предупреждение о бюджете GCP и IMAGE_MCP_RATE_PER_HOUR. Предел дедупликации считается на каждый instance, поэтому фактический потолок — IMAGE_MCP_RATE_PER_HOUR × --max-instances.

Related MCP Connectors

Related MCP Servers