Claude → OpenAI Image Generation via a Custom MCP Connector
An OAuth 2.1-secured MCP server, built into an existing Next.js app, that lets anyone on the team generate and edit images with OpenAI's image models directly inside Claude, which has no native connector for them.
Workflow
From “Claude calls generate_image or edit_image” to result
- 1. Trigger
Add connector URL
A team member adds one custom connector URL in claude.ai or Claude Desktop.
- 2. Action
Discover & register
Claude finds the auth endpoints through protected-resource and authorization-server metadata (RFC 9728, RFC 8414) and registers itself as a client (RFC 7591).
- 3. Action
Google sign-in
PKCE (S256) is mandatory. Login uses the same Google account as the app, with the same email and domain allow-lists.
- 4. Action
Tokens issued
Stateless signed JWTs: a 1-hour access token and a 30-day refresh token. No token database.
- 5. Action
Claude calls a tool
generate_image (text to a batch of images) or edit_image (images plus text to edited variants), 3 images by default.
- 6. Action
OpenAI generates
The server calls OpenAI's gpt-image models with the requested size, quality, background and format.
- 7. Output
Images inline in Claude
Returned as base64 at full resolution and lossless, so they render in Claude chat and Claude Desktop and work inside Claude artifacts.
OAuth 2.1 for an MCP connector, explained
THE CONCEPT
OAuth 2.1 sign-in for an MCP connector
THINK OF IT LIKE
Checking in at a hotel
OAuth 2.1 sign-in for an MCP connector is like Checking in at a hotel
- OAuth metadata discoveryis like Signs in the lobby pointing to reception
- Dynamic client registrationis like Filling in the registration card
- Google sign-in with allow-listsis like Showing ID that's on the guest list
- 1-hour access tokenis like A key card that stops working soon
- 30-day refresh tokenis like Re-coding the card at the desk without checking in again
Problem
The team works in Claude, but Claude has no native connector for OpenAI's image models. Generating an image meant leaving Claude, using another tool, and bringing the result back.
Architecture
The MCP server lives inside the existing Next.js app at POST /api/mcp. It needs no extra infrastructure and reuses the app's HTTPS origin. The app is its own OAuth 2.1 authorization server. It publishes RFC 9728 protected-resource metadata and RFC 8414 authorization-server metadata so clients can discover it automatically, and supports RFC 7591 dynamic client registration so Claude can register itself. PKCE with S256 is mandatory. Sign-in goes through the same Google account as the app, with the same allow-lists, so nobody gets access to the connector who couldn't already use the app. Tokens are stateless signed JWTs (signed with jose): 1-hour access tokens and 30-day refresh tokens, with no token database to run. For clients that can't do OAuth, such as Claude Desktop through mcp-remote, an optional static bearer token is supported. The server exposes two tools. generate_image takes a prompt plus n (default 3), size, quality, background, output format and model. edit_image takes one or more image paths plus a prompt and returns edited variants.
One image request, end to end
sequenceDiagram participant U as Team member participant C as Claude participant S as App MCP server participant G as Google sign-in participant O as OpenAI gpt-image U->>C: add connector URL C->>S: fetch OAuth metadata C->>S: register client C->>G: sign in with PKCE G-->>S: verified Google account S-->>C: 1-hour access token U->>C: image prompt C->>S: generate_image (token) S->>O: image request O-->>S: images S-->>C: base64 images inline C-->>U: images in chat
Input
A prompt, and for edits one or more source images, sent by Claude as an MCP tool call along with optional size, quality, background, output format and model.
Output
A batch of images returned inline as base64 at full resolution and lossless. Returning them inline instead of as links matters: Claude artifacts run in a sandbox that blocks external URLs, so a link would not render there.
Integrations
Limitations
It covers image generation and editing only. The static bearer token is a fallback for clients that can't do OAuth; it skips the Google sign-in and its allow-lists.
Security Notes
OAuth 2.1 with mandatory PKCE (S256). Login is restricted by the app's email and domain allow-lists. Access tokens expire after 1 hour and refresh tokens after 30 days. The OpenAI API key lives only in server environment variables and is never exposed to Claude or the client. The app refuses to boot with a weak or missing signing secret.
Learnings
Building the MCP server into the existing app, rather than as a separate service, meant no new infrastructure and the same sign-in the team already used. Self-describing OAuth metadata plus dynamic client registration is what makes "paste one URL, sign in with Google" possible.