Pixel Bridge MCP
Bridges Claude Code to ChatGPT and Gemini web interfaces for free AI image generation, using Playwright to automate browser logins without API keys.
README
Pixel Bridge MCP
Free AI image generation for Claude Code — through the ChatGPT and Gemini web accounts you already have. A local MCP server that drives a real browser (Playwright) against provider web UIs, so you get generate_image / edit_image tools without any image-generation API keys. You log in manually once; Claude Code reviews the results with its own vision.
Bridges Claude Code → your browser → ChatGPT / Gemini image generation. Hence the name.
How it works
Claude Code ──MCP──> Pixel Bridge ──Playwright──> your logged-in browser profile
├─ chatgpt.com
└─ gemini.google.com
image saved to ./assets/… <── actual generated file downloaded
Claude Code reads the file with its own vision and judges quality itself.
Key principles:
- You authenticate manually, once. Each provider gets a persistent Chromium profile (
~/.pixel-bridge/profiles/<provider>). Log in yourself — including any CAPTCHA or MFA. The server never touches credentials and never attempts to bypass security challenges. - The MCP is not the art critic. It returns file paths + metadata; the calling Claude Code model inspects the image visually and decides whether to keep it or regenerate with a better prompt.
- Never silently "succeeds". If the real image bytes couldn't be retrieved, the job fails with a reason (refusal text, timeout, UI change, capture failure) and a debug screenshot is saved to
~/.pixel-bridge/logs/.
Setup (on your machine)
Option A — Managed browser (default)
git clone https://github.com/Mrshahidali420/pixel-bridge-mcp
cd pixel-bridge-mcp
npm install
npx playwright install chromium # once
npm run build
# One-time manual login per provider (opens a visible browser window):
npm run login -- chatgpt
npm run login -- gemini
Tip: set PIXEL_BRIDGE_BROWSER_CHANNEL=chrome to use your installed Google Chrome instead of the bundled Chromium.
Option B — Attach to your own browser (use your existing logins)
Instead of letting Pixel Bridge launch its own browser, you can attach it to a real Chrome/Edge/Brave you started, and it will use whatever logins that browser already has. Start your browser with a debugging port and a dedicated profile folder:
# Windows (PowerShell)
& "C:\Program Files\Google\Chrome\Application\chrome.exe" `
--remote-debugging-port=9222 --user-data-dir="$env:LOCALAPPDATA\pixel-bridge-chrome"
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 --user-data-dir="$HOME/pixel-bridge-chrome"
# Linux
google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/pixel-bridge-chrome"
Log into chatgpt.com / gemini.google.com in that window (once — the profile persists), then run the MCP with:
PIXEL_BRIDGE_CDP_URL=http://127.0.0.1:9222
Pixel Bridge opens its own tabs in that browser, never touches your tabs, and on shutdown closes only its tabs and disconnects — your browser keeps running. You can watch every generation live and handle any login challenge in the same window.
Why not my normal day-to-day Chrome profile? Chrome itself refuses remote debugging on the default profile (a security measure since Chrome 136 that protects your cookies from debugger-based theft), and a running Chrome locks its profile. That's why attach mode needs a dedicated
--user-data-dir— you still sign in only once there, and it stays signed in like your normal browser. Pixel Bridge does not attempt to bypass this protection.
Register with Claude Code — add to your project's .mcp.json (or claude mcp add):
{
"mcpServers": {
"pixel-bridge": {
"command": "node",
"args": ["/absolute/path/to/pixel-bridge-mcp/dist/index.js"]
}
}
}
Tools
| Tool | Purpose |
|---|---|
generate_image |
Generate via chatgpt or gemini; saves locally; returns paths + metadata. |
edit_image |
Upload a local image + edit instructions; saves the edited result. |
generate_with_both |
Same prompt through both providers in parallel → two files to compare. |
get_generation_status |
Poll a slow job by job_id (optionally block up to wait_seconds). |
download_generated_image |
Copy a completed job's image(s) to an additional location. |
check_provider_session |
Is the persistent session logged in and usable? |
provider_login |
Open the provider site (headed) and wait while you log in manually. |
Job model (a deliberate design change from the original spec)
Web generation can take minutes, which can exceed MCP client timeouts. So every generation runs as a background job that saves its own output:
generate_imagewaits inline (default 150 s). Usually the site finishes in time and you get the saved file paths directly.- If not, you get a
job_idwith statusrunning— pollget_generation_status. - The job writes the image to the originally requested
output_pathwhen it finishes, even if no one is polling — a client timeout never loses a finished image.download_generated_imageis therefore only for extra copies.
File handling
output_pathmay be a file (./assets/hero.png) or a directory (filename auto-derived, or passfilename).- Directories are created automatically. PNG / JPEG / WebP supported — the extension follows the actual content type delivered by the provider.
- Existing files are never overwritten unless
overwrite: true; a-1,-2… suffix is used instead. - Results include both absolute and project-relative paths, byte size, content type, and
capture_method:"download"— the real generated file was fetched (full quality)."screenshot"— last-resort element screenshot fallback (reported honestly so Claude can decide to retry).
Aspect ratio
Web UIs expose no reliable aspect-ratio control, so aspect_ratio (e.g. "16:9") is folded into the prompt as natural language. Verify the result visually — the tool output reminds the calling model to check this.
Intended Claude Code workflow
- Ask
generate_image(orgenerate_with_both) with a concrete prompt, e.g. a 16:9 hero image spec. - Read the returned file with vision.
- Judge: prompt match, composition, artifacts, hands/faces, unwanted text/watermarks, aspect ratio.
- Keep it, or refine the prompt and regenerate. The MCP never scores quality itself.
Architecture
src/
├── index.ts MCP server + tool definitions (stdio transport)
├── cli-login.ts `npm run login -- <provider>` first-run helper
├── config.ts env-driven config (no credentials, no hardcoded paths)
├── logger.ts stderr + rolling file logs (stdout is MCP protocol)
├── files.ts path resolution, mkdir, collision-free naming
├── jobs.ts background job manager (client timeouts can't lose images)
├── browser.ts persistent Chromium profile per provider + per-provider queue
└── providers/
├── types.ts ImageProvider interface
├── base.ts shared choreography: selector fallbacks, new-image detection,
│ busy/refusal detection, download-with-screenshot-fallback
├── chatgpt.ts ChatGPT web adapter (~60 lines of provider-specific config)
├── gemini.ts Gemini web adapter (~70 lines)
└── registry.ts add future providers here
Reliability decisions:
- No brittle DOM assumptions: each provider supplies candidate selector lists tried in order; results are detected generically as "a new ≥300 px image appeared and stayed stable after the model stopped responding", not via provider DOM structure.
- Refusal detection: if the model finishes replying with no image, the reply text is returned in the error so Claude can rephrase.
- Per-provider serialization: concurrent calls to one provider queue up; different providers run in parallel (that's how
generate_with_bothworks). - Debuggability: every failure saves a page screenshot to
~/.pixel-bridge/logs/, and job results include recent step-by-step logs.
Configuration (env vars, all optional)
| Variable | Default | Meaning |
|---|---|---|
PIXEL_BRIDGE_HOME |
~/.pixel-bridge |
Profiles + logs root |
PIXEL_BRIDGE_PROFILE_DIR |
<home>/profiles |
Browser profiles location |
PIXEL_BRIDGE_HEADLESS |
false |
Headed is the default — friendlier to consumer sites and required for manual login |
PIXEL_BRIDGE_BROWSER_CHANNEL |
– | e.g. chrome to use your installed Chrome instead of bundled Chromium |
PIXEL_BRIDGE_EXECUTABLE_PATH |
– | Explicit browser binary path |
PIXEL_BRIDGE_CDP_URL |
– | Attach mode: connect to your own running browser (e.g. http://127.0.0.1:9222) instead of launching one |
PIXEL_BRIDGE_GENERATION_TIMEOUT_S |
300 |
Hard ceiling per generation |
PIXEL_BRIDGE_DEFAULT_WAIT_S |
150 |
Default inline wait before returning a job id |
PIXEL_BRIDGE_LOGIN_TIMEOUT_S |
300 |
Manual-login wait |
HTTPS_PROXY |
– | Forwarded to the browser when set (corporate proxies) |
Security posture
- No credentials in code, config, or logs; nothing to hardcode.
- Sessions live only in the local browser profile —
.gitignoreexcludes profiles; never commit them (they contain live cookies). - CAPTCHAs, MFA, and bot checks are never automated. When a provider challenges, the tools report it and
provider_loginhands control to you in a visible window. - Respect each provider's terms of service; this drives your own account through its normal web UI at human-triggered, low volume.
Status / what's been verified
Built and smoke-tested in a headless cloud environment:
- ✅ Compiles clean; server starts and serves all 7 tools over MCP stdio.
- ✅ File naming/collision/extension logic verified with unit checks.
- ✅ Job lifecycle, error propagation, and failure screenshots verified.
- ⏳ The live browser flows (login → generate → download) need a run on a real desktop — the cloud sandbox has no display, blocks chatgpt.com entirely, and its TLS-intercepting proxy interferes with Playwright-driven navigation. First local test:
npm run login -- gemini, then ask Claude Code to generate a test image into./assets/.
Adding a provider later
Implement BaseChatProvider (URLs, selector candidates, logged-in/busy detection, prompt phrasing — see chatgpt.ts for how small that is) and register it in providers/registry.ts. Non-chat UIs can implement the ImageProvider interface directly.
Contributing
Contributions are very welcome — especially selector fixes when provider UIs change and new provider adapters (Bing Image Creator, Ideogram, Playground, …). See CONTRIBUTING.md for setup, the adapter guide, and the hard rules (no credential handling, no CAPTCHA/MFA/bot-detection bypassing, no silent success). If this project is useful to you, a ⭐ helps others find it.
License
MIT © Shahid Ali
Disclaimer
Pixel Bridge automates your own account through its normal web interface at human scale. Respect each provider's terms of service and rate limits; you are responsible for how you use it. This project is not affiliated with OpenAI, Google, or Anthropic.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。