Skip to main content
Glama

image-gen-mcp

一个使用 Google Gemini 原生图像模型(“Nano Banana”)生成图像的 MCP 服务器,通过 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 需要高性能模型 并且需要存储桶

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 的 API 密钥

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 需要)

存储超大图像的桶

服务器坚持“宁可启动失败,也不在错误配置下运行”——缺少 API 密钥、完全没有认证边界(既没有静态令牌也没有代理模式)这两种情况都会导致启动失败。

身份验证

两种表现形式并不存在,服务端会拒绝未采用这两种模式之一的情况。

(生产环境)代理之后。 设置 IMAGE_MCP_TRUST_PROXY_HEADERS=1。代理会使用 Google 验证用户身份。并执行其本身的允许列表、取消客户端的 Authorization 请求标头。并将身份以 X-Auth-Email / X-Auth-Subject / X-Auth-Scope 转发。该服务器会读取这些内容,并且不需要自己的令牌——没有 X-Auth-Email 的请求将返回 401。

信任请求标头的安全性 只 是因为没有其他方式可以访问这个进程。在 Cloud 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 或 GOOGLE_OAUTH_CLIENT_SECRET 设置为启动错误(而非静默地忽略)——这些应在代理上配置。

构建映像

.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)之前的透明缓存会愉快地传播旧镜像;摘要却不可能过期。每次运行都会将摘要显示到其作业摘要中,并且如果你希望在一条流水线中同时构建和部署此工作流程,它是可调用的:

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需要支持 read:packages,或者在 GitHub 包设置中将该包设为公开。

部署

由 cloudrun-mcp-deployment 部署(.github/workflows/deploy-image-gen-mcp.yml),以 Cloud Run 多容器服务中后端容器的身份运行此镜像,并采用 mcp-oauth-proxy 放在前端。该仓库负责 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(即代理所在的容器)的容器接收网络流量,这意味着后端的访问只来自实例内部。

用于 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

遗漏 storage.objectViewer 多数是签名链接失效的最常见原因 serviceAccountTokenCreator 绑定是最常见的签名 URL 出错原因。

测试

uv run pytest -q

57 个测试:启动保护性检查、两种模式的身份解析(代理头部、静态令牌,以及它们各自忽略对方的凭证信息)、工具验证和数据传递行为确认,以及以其实 MCP 客户端通过真实 HTTP 与 uvicorn 对接进行端到端的冒烟测试——包括令牌模式和代理后的生产环境模式运行。

费用成本

每个已授权用户都是基于同一个 API 密钥进行汇总消费。下面的监控控制计数器按实际效果排序:CLOUD_RUN 最大实例副本数 --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