Skip to main content
Glama

gemini-image-mcp

MCP server cho AI Image Studio: agent vừa chạy service (bridge), vừa gọi API tạo ảnh — ảnh do Gemini sinh trong chính trình duyệt của bạn, kết quả trả về dưới dạng file.

MCP client (Claude Desktop / Cursor / VS Code)
      │  stdio
      ▼
gemini-image-mcp  ──►  bridge (127.0.0.1)  ──►  trang studio trong trình duyệt  ──►  Gemini

4 tool: bridge_status · bridge_start · bridge_stop · image_generate

Bắt đầu trong 3 bước

1. Thêm config vào MCP client

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json; Windows: %APPDATA%\Claude\claude_desktop_config.json):

{
  "mcpServers": {
    "gemini-image-mcp": {
      "command": "npx",
      "args": ["-y", "github:nguyennamkkb/gemini-image-mcp"]
    }
  }
}

Cursor (~/.cursor/mcp.json) và VS Code (.vscode/mcp.json): cùng dạng mcpServers ở trên (VS Code còn nhận {"servers": {…: {"type": "stdio", …}}}).

opencode — dùng 2 dòng ngắn (đừng dán 1 dòng dài, dễ bị xuống dòng làm github:… thành lệnh riêng):

SPEC=github:nguyennamkkb/gemini-image-mcp
opencode mcp add --global gemini-image-mcp -- npx -y $SPEC
opencode mcp list        # phải thấy "✓ gemini-image-mcp connected" (lần đầu chờ ~10s cho npx tải)

Hoặc viết tay vào ~/.config/opencode/opencode.json (toàn cục) hay opencode.json ở gốc project:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "gemini-image-mcp": {
      "type": "local",
      "command": ["npx", "-y", "github:nguyennamkkb/gemini-image-mcp"],
      "enabled": true,
      "timeout": 30000
    }
  }
}

Hai điểm bắt buộc phải biết cho opencode:

  • Đặt timeout ≥ 30000. Lần chạy đầu npx phải tải package (~9s đo thực tế), mà mặc định opencode chỉ chờ 5000ms để lấy danh sách tool → server hiện pending/failed dù cấu hình đúng.

  • opencode.json ở gốc project chỉ được đọc khi thư mục đó là git workspace (ngoài git repo opencode báo "No MCP servers configured"). Muốn dùng mọi nơi thì thêm --global như trên.

  • Shape phẳng "mcp": {"gemini-image-mcp": {…}} (như trên) và shape lồng "mcp": {"servers": {…}} (CLI v2 sinh ra) đều chạy — đã thử cả hai trên opencode 2.0.32.

Config trên luôn lấy bản mới nhất từ nhánh main. Muốn cố định, thêm #v1.0.2 (hoặc commit sha) vào sau tên repo, ví dụ github:nguyennamkkb/gemini-image-mcp#v1.0.2.

2. Khởi động lại client (thoát hẳn rồi mở lại). Trong danh sách tool phải thấy đủ 4 tool ở trên.

3. Mở trang studio thành worker. Nhờ agent gọi bridge_start — nó trả về pageUrl (dạng http://127.0.0.1:8765/?token=…). Mở link đó trong Chrome rồi để yên tab đấy. Sau đó image_generate mới có worker để chạy.

Đang dùng Gemini Canvas (để Canvas cấp key Gemini) thì gọi bridge_start {"allowCanvas": true} và mở trang studio trong tab Canvas — xem ràng buộc trình duyệt.

Related MCP server: Nano Banana

Workflow đang dùng: Gemini Canvas (1–1)

Cách dùng cố định của máy này — worker là tab Gemini Canvas, không phải tab local. Mọi thứ khác chạy tự động; đọc mục này trước khi sửa/nâng cấp để không đi lạc hướng.

opencode ──stdio──► gemini-image-mcp ──HTTP/WS──► bridge (127.0.0.1:8765)
                                                      ▲
                                     HTTP long-poll  │  (Canvas cấm WebSocket)
                                                      │
                                  tab Gemini Canvas (ai_image_studio.html) ──► Gemini
                                  (Canvas tự cấp key — KHÔNG cần key trong trang)

1. Config MCP (opencode.json ở gốc project)

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "gemini-image-mcp": {
      "type": "local",
      "command": ["npx", "-y", "github:nguyennamkkb/gemini-image-mcp"],
      "enabled": true,
      "timeout": 30000,
      "environment": {
        "AI_STUDIO_ALLOW_CANVAS": "true",
        "AI_STUDIO_TOKEN": "aistudio-1-1-7f2c9d41b8e35a60"
      }
    }
  }
}

Dòng

Vì sao cần

timeout: 30000

Lần đầu npx tải package ~9s; mặc định opencode chờ 5000ms → server hiện pending dù đúng config

AI_STUDIO_ALLOW_CANVAS: "true"

Bridge tự start (do image_generate) luôn có --allow-canvas → nhận worker Canvas

AI_STUDIO_TOKEN

Token cố định để bridge ↔ trang bắt tay, không lệch khi file ~/.ai-image-studio/.token bị xoá

Giá trị cần dán vào tab Canvas (một lần, localStorage giữ mãi):

  • URL: ws://127.0.0.1:8765/ws

  • Token: aistudio-1-1-7f2c9d41b8e35a60

Để trống ô token cũng được — trang tự dò qua GET /api/discover (endpoint này trả token), nên hai bên luôn khớp kể cả khi bạn quên.

Nếu dùng Claude Code (.mcp.json) — cùng env nhưng tên key khác:

{
  "mcpServers": {
    "gemini-image-mcp": {
      "command": "npx",
      "args": ["-y", "github:nguyennamkkb/gemini-image-mcp"],
      "env": { "AI_STUDIO_ALLOW_CANVAS": "true", "AI_STUDIO_TOKEN": "aistudio-1-1-7f2c9d41b8e35a60" }
    }
  }
}

opencode

Claude Code

Ghi chú

mcp

mcpServers

key gốc — mcpServers KHÔNG có tác dụng với opencode (và ngược lại)

command (mảng)

command (chuỗi) + args (mảng)

environment

env

biến cho tiến trình server (đặt AI_STUDIO_* ở đây)

timeout: 30000

—

Claude Code chỉnh bằng env MCP_TIMEOUT / MCP_TOOL_TIMEOUT của client, đặt trong env của server là vô tác dụng: export MCP_TOOL_TIMEOUT=600000 (ảnh có thể mất vài phút)

2. Chrome phải tắt Local Network Access (Chrome 142+)

Trang Canvas là origin https://…usercontent.goog; Chrome 155 chặn nó gọi http://127.0.0.1 → mọi cổng báo Failed to fetch. Bắt buộc mở Chrome kèm cờ:

# alias đã có trong ~/.zshrc:
alias chromedev='open -na "Google Chrome" --args --disable-features=LocalNetworkAccessChecks'

pkill -f "Google Chrome"   # PHẢI thoát hẳn Chrome trước khi chạy chromedev
chromedev                  # dùng profile mặc định (giữ đăng nhập Google/Gemini)

# kiểm chứng cờ đã vào (kỳ vọng ≥1):
ps aux | grep "Contents/MacOS/Google Chrome" | grep -v grep | grep -c LocalNetworkAccessChecks

3. Vận hành hằng ngày

  1. chromedev → mở lại tab Gemini Canvas chứa ai_image_studio.html → để yên tab đó

  2. Gọi image_generate {"prompt": "…"} từ opencode — bridge tự start, tự chờ worker, trả filePath

  3. Tab Canvas hiện Đang tạo ảnh / worker h_… HTTP long-poll là dấu hiệu đúng

Quy tắc bất di bất dịch

  • KHÔNG sửa ai_image_studio.html. Bản trong tab Canvas là bản bạn đã dán; sửa file trong repo sẽ làm lệch hai bên và gây nhầm lẫn. Mọi bản vá nằm ở bridge/ + mcp/.

    • Ngoại lệ đã chấp nhận (1.0.9): ô token trong panel "Cấu hình API local" đổi type="password" → type="text" để nhìn thấy token cố định cho tiện đối chiếu hai bên. Đây là token local (loopback + origin policy), không phải khoá Gemini. Sửa trên do người dùng chủ động; tab Canvas muốn thấy y hệt thì dán lại ai_image_studio.html mới vào Canvas một lần.

  • Không cần key Gemini trong trang (Canvas cấp) và không cần dán token (tự dò).

  • Chỉ cần 1 worker (tab Canvas). Bridge ở chế độ canvas không mở tab local nữa, nên không có chuyện job rơi vào tab không key (xem bảng sự cố bên dưới).

4. Nâng cấp lên bản mới (repo không dùng tag, luôn theo main)

# phía repo (người phát hành):
#   1) sửa code → 2) tăng "version" trong package.json → 3) commit & push main
git commit -am "..." && git push origin main

# phía máy dùng (bắt buộc, nếu không npx vẫn dùng bản cũ đã cache):
rm -rf ~/.npm/_npx/*/node_modules/gemini-image-mcp ~/.npm/_npx/<hash>
# rồi thoát hẳn opencode và mở lại → npx tải bản mới

Kiểm tra đang chạy bản nào:

opencode mcp list                     # phải thấy ✓ gemini-image-mcp connected
# trong phiên: gọi bridge_status {}   → "version" của bridge
#              initialize (client tự gọi) → serverInfo.version = version trong package.json
python3 -c "import json;print(json.load(open('$(ls -d ~/.npm/_npx/*/node_modules/gemini-image-mcp/package.json | head -1)'))['version'])"

Muốn cố định một bản thay vì theo main: thêm #<commit-sha> sau tên repo trong command.

5. Sự cố thường gặp (đã gặp thật, kèm cách sửa)

Triệu chứng

Nguyên nhân

Cách sửa

Trang Canvas: mọi cổng Failed to fetch

Chrome chặn LNA (142+)

Thoát hẳn Chrome → chromedev → mở lại tab Canvas

origin-not-allowed / HTTP 403 từ origin Canvas

Bridge chạy thiếu --allow-canvas

Từ 1.0.5: bridge_start {allowCanvas:true} tự dừng + start lại bridge thiếu quyền; hoặc đặt AI_STUDIO_ALLOW_CANVAS=true

502 Method doesn't allow unregistered callers

Tab local (?token=…) không có key Gemini lại nhận job

Từ 1.0.6: bridge chế độ canvas không mở tab local → đóng tab local nếu còn mở

503 chưa có worker

Tab Canvas chưa mở/chưa bấm "Thử lại"

bridge_status → mở tab Canvas theo pageUrl/panel

Server pending/failed trong opencode

timeout < 30000, hoặc config sai key (mcpServers là của Claude, opencode dùng mcp)

Sửa opencode.json như mục 1

Bridge start nhưng token lệch với trang

Token ngẫu nhiên bị sinh lại (xoá ~/.ai-image-studio/.token)

Dùng AI_STUDIO_TOKEN cố định như mục 1

Dừng dịch vụ khi cần: bridge_stop {"port": 8765} (chỉ kill khi /api/status xác nhận đúng bridge).

Dùng

bridge_status {}                               → bridge nào đang chạy, worker nào nối, link mở trang
bridge_start  {"allowCanvas": true}            → chạy service nền, trả pageUrl + pid + logFile
image_generate {"prompt":"mèo phi hành gia, 3D cinematic","aspectRatio":"16:9"}
image_generate {"prompt":"biến thể lúc hoàng hôn","refImagePath":"/tmp/in.png","inline":true}
bridge_stop   {"port":8765}                    → dừng bridge (chỉ kill khi /api/status xác nhận đúng bridge)

image_generate trả về {ok, filePath, bytes, mime, aspectRatio, tookMs, workerId}; đặt inline:true để kèm luôn ảnh vào kết quả cho client hiển thị.

Dữ liệu lưu ở đâu

Đường dẫn

Nội dung

<project đang gọi tool>/generated-images/

Ảnh tạo ra khi client chạy trong một project (opencode/Cursor/VS Code spawn MCP server với cwd = gốc workspace, đã đo thực tế)

~/Pictures/ai-image-studio/

Ảnh tạo ra khi không xác định được project (ví dụ Claude Desktop)

~/.ai-image-studio/.token

Token bí mật để local API/bridge xác thực (sinh tự động, quyền 600)

~/.ai-image-studio/logs/

Log của bridge do MCP chạy nền

~/.ai-image-studio/.bridge-state.json

pid/port của bridge mà MCP đã chạy (để bridge_stop biết)

Hai biến môi trường để đổi chỗ lưu (thêm vào "env" trong config nếu cần):

Biến

Mặc định

Ý nghĩa

AI_STUDIO_HOME

~/.ai-image-studio

Token, log, state của bridge

AI_STUDIO_OUTPUT

(tự chọn theo project)

Ép nơi lưu ảnh, ghi đè cả quy tắc theo project

AI_STUDIO_ALLOW_CANVAS

(tắt)

true → bridge tự start (bởi image_generate) luôn mang --allow-canvas, sẵn sàng nhận worker Gemini Canvas

AI_STUDIO_START_ARGS

(trống)

Chèn thêm tham số cho bridge tự start, ví dụ --allow-origin https://your-host

AI_STUDIO_TOKEN

(tự sinh)

Token cố định để bridge ↔ trang studio bắt tay (thay vì token ngẫu nhiên sinh một lần rồi lưu ở ~/.ai-image-studio/.token). Đặt trong env của config MCP ⇒ bridge và MCP dùng chung đúng một token, dán vào trang Canvas một lần là dùng mãi. Tên cũ BRIDGE_TOKEN vẫn chấp nhận

Ảnh lưu vào đâu

Thứ tự ưu tiên (cao → thấp), mỗi kết quả image_generate đều trả filePath + outputDir + outputSource để biết vì sao:

  1. savePath — đường dẫn file chính xác truyền trong lệnh.

  2. outputDir — thư mục truyền trong lệnh (tự đặt tên file).

  3. AI_STUDIO_OUTPUT — biến môi trường.

  4. <project đang gọi tool>/generated-images — khi cwd của server là một project (có .git/package.json).

  5. ~/Pictures/ai-image-studio — khi không xác định được project.

Muốn ảnh luôn vào project hiện tại khi dùng opencode thì không cần làm gì thêm (nó spawn server ở gốc workspace). Muốn đổi chỗ khác thì đặt AI_STUDIO_OUTPUT trong "environment"/"env" của config.

Yêu cầu

  • Node ≥ 20 (MCP server + bridge đều zero-dependency ngoài SDK chính thức).

  • Một trang studio đang mở làm worker: hoặc mở link bridge (pageUrl) trong Chrome, hoặc dán ai_image_studio.html vào Gemini Canvas (Canvas cấp key Gemini nên không cần API key).

Vì sao phải có trang studio mở

Ảnh do Gemini sinh trong trình duyệt (Canvas tự inject key), nên luôn cần ít nhất một worker là trang ai_image_studio.html đang mở. Trình duyệt cũng chặn khá nhiều đường về máy local, và bridge đã xử lý từng trường hợp:

Trang chạy ở

Rào cản

Cách dùng

http://127.0.0.1:8765/ (link pageUrl)

không có

Mở link, xong. WebSocket chạy luôn

Tab Gemini Canvas

Canvas cấm new WebSocket; Chrome chặn Local Network Access với origin công khai; origin Canvas không phải loopback

bridge_start {"allowCanvas": true} + Chrome chạy kèm --disable-features=LocalNetworkAccessChecks

Origin khác (host LAN, https khác)

như trên, và phải khai báo origin

bridge_start {"allowOrigin": ["https://your-host"]}

Chi tiết + bằng chứng đo được: bridge/README.md. MCP: mcp/README.md.

Phát triển

npm install
npm run smoke                                  # handshake + tools/list + bridge_status + kiểm tra đường dẫn
npm run smoke -- --with-service                # thêm vòng đời start → status → stop
npm run smoke -- --with-image                  # thêm tạo ảnh thật (cần worker đang mở)
npm pack                                       # gói phát hành, kiểm tra nội dung .tgz

Cấu trúc:

Đường dẫn

Vai trò

mcp/server.mjs

MCP server (stdio) + 4 tool

mcp/smoke-test.mjs

Test qua stdio JSON-RPC thật

bridge/server.mjs

Bridge: WS hub + HTTP API + HTTP long-poll cho Canvas

ai_image_studio.html

Trang studio (UI + client bridge)

Phát hành bản mới

Không dùng tag — người dùng luôn lấy bản mới nhất từ main:

  1. Sửa code, tăng version trong package.json (version này được MCP trả trong initialize nên kiểm tra được đang chạy bản nào).

  2. git commit && git push origin main

  3. Người dùng chạy lại client là xong (npx sẽ lấy bản mới). Ai muốn cố định thì pin github:nguyennamkkb/gemini-image-mcp#<commit-sha>.

Các tag cũ (v1.0.0 → v1.0.2) vẫn còn trên remote để ai đang pin thì không gãy; xoá bằng git push origin :refs/tags/v1.0.0 nếu không muốn giữ.

License

MIT — xem LICENSE.

Related MCP Connectors

Related MCP Servers