{
  "markdown": "# mcp-imagenate\n\n<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/mimo-3/mcp-imagenate/main/imagenerate-cat.png\" alt=\"mcp-imagenate\" width=\"400\">\n</p>\n\nAn MCP server for image generation using multiple providers: **Google Gemini**, **OpenAI (gpt-image)**, **BFL FLUX**, and **Reve** — plus short video clips through **Google Gemini Omni**.\n\n## Providers & Models\n\n### Google Gemini (Nano Banana)\n\n| Name              | Model ID                         | Best for                     |\n| ----------------- | -------------------------------- | ---------------------------- |\n| `nano-banana-2`   | `gemini-3.1-flash-image-preview` | Fast, high-volume generation |\n| `nano-banana-pro` | `gemini-3-pro-image-preview`     | Highest quality output       |\n\n### Google Gemini Omni (video)\n\n| Name         | Model ID               | Best for                                   |\n| ------------ | ---------------------- | ------------------------------------------ |\n| `gemini-omni-1.1-flash` | `gemini-omni-1.1-flash` | 3–10 s clips with audio, legible on-screen text |\n\nUses the same `GEMINI_API_KEY`. Exposed through a separate `generate_video` tool —\nsee [Tool: `generate_video`](#tool-generate_video).\n\n### OpenAI\n\n| Name          | Model ID      | Best for                           |\n| ------------- | ------------- | ---------------------------------- |\n| `gpt-image-2` | `gpt-image-2` | Latest generation, improved detail |\n\nThese are the only models here that can return a transparent background — see\n[Transparent backgrounds](#transparent-backgrounds).\n\n### BFL FLUX\n\n| Name            | Model ID      | Best for                         |\n| --------------- | ------------- | -------------------------------- |\n| `flux-2-klein`  | `klein-4b`    | Fast, lightweight generation     |\n| `flux-2-pro`    | `pro-preview` | Balanced quality and speed       |\n| `flux-2-max`    | `max`         | Maximum quality                  |\n\n### Reve\n\n| Name         | Version  | Best for                       |\n| ------------ | -------- | ------------------------------ |\n| `reve-image` | `latest` | Typography and layout fidelity |\n\nThis provider calls Reve's `v2/image/create` endpoint. `latest` is the only version\nalias v2 exposes, and it is what the response reports back, so there is no dated\nbuild to pin to. Do not confuse it with the `v1` endpoints, which still serve the\nolder `reve-create@20250915` model.\n\nThings worth knowing before sending Reve a prompt written for another provider:\n\n- `resolution` is ignored — Reve has no size parameter and returns its own large\n  output. Exact dimensions vary between requests: `16:9` came back as both\n  5408x3072 and 5376x3072, and `3:4` as 3456x4800.\n- Prompts are capped at 4,000 characters, and this provider rejects longer ones\n  before spending a request.\n- `inputImages` become v2 `references`. Reve accepts at most eight; a longer list\n  is rejected before any of the files are read.\n- The saved file's extension follows the format Reve actually returned (PNG, JPEG\n  or WebP), which is detected from the bytes rather than assumed.\n- A generation costs 150 credits (about $0.20) and typically takes 40-80 seconds.\n  Give any proxy or job runner in front of it a timeout of at least 120 seconds.\n\n## Requirements\n\n- Node.js 20+\n- At least one provider API key\n\n## Installation\n\n```bash\nnpx mcp-imagenate\n```\n\nOr install globally:\n\n```bash\nnpm install -g mcp-imagenate\n```\n\n## Setup\n\nSet API keys for the providers you want to use:\n\n```bash\n# Google Gemini (at least one)\nexport GEMINI_API_KEY=your_key_here\n# or\nexport NANO_BANANA_API_KEY=your_key_here\n\n# OpenAI (at least one)\nexport OPENAI_API_KEY=your_key_here\n# or\nexport GPT_IMAGE_API_KEY=your_key_here\n\n# BFL FLUX\nexport BFL_API_KEY=your_key_here\n\n# Reve (at least one)\nexport REVE_API_KEY=your_key_here\n# or\nexport REVE_API_TOKEN=your_key_here\n```\n\n### Claude Desktop\n\nAdd to your `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"mcp-imagenate\": {\n      \"command\": \"npx\",\n      \"args\": [\"mcp-imagenate\"],\n      \"env\": {\n        \"GEMINI_API_KEY\": \"your_key_here\",\n        \"NANO_BANANA_OUTPUT_DIR\": \"/path/to/image/output\"\n      }\n    }\n  }\n}\n```\n\n## Environment Variables\n\n| Variable                  | Required | Description                                                                                                   |\n| ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- |\n| `GEMINI_API_KEY`          | \\*       | Google AI Studio API key                                                                                      |\n| `NANO_BANANA_API_KEY`     | \\*       | Alternative to `GEMINI_API_KEY` (takes precedence)                                                            |\n| `OPENAI_API_KEY`          | \\*       | OpenAI API key                                                                                                |\n| `GPT_IMAGE_API_KEY`       | \\*       | Alternative to `OPENAI_API_KEY` (takes precedence)                                                            |\n| `BFL_API_KEY`             | \\*       | BFL FLUX API key                                                                                              |\n| `REVE_API_KEY`            | \\*       | Reve partner API token (from the API console at api.reve.com)                                                 |\n| `REVE_API_TOKEN`          | \\*       | Alternative to `REVE_API_KEY` (`REVE_API_KEY` takes precedence)                                               |\n| `NANO_BANANA_OUTPUT_DIR`  | No       | Base directory for saved images. When set, all output and input paths are sandboxed within this directory. **Recommended for production.** |\n\n\\* At least one provider API key must be set.\n\n## Tool: `generate_image`\n\n### Parameters\n\n| Parameter      | Type                                                   | Default           | Description                                                                   |\n| -------------- | ------------------------------------------------------ | ----------------- | ----------------------------------------------------------------------------- |\n| `prompt`       | `string` (1-32,000 chars)                              | -                 | Text prompt describing the image                                              |\n| `model`        | see Models above                                       | `\"gpt-image-2\"`   | Model to use (available models depend on configured API keys)                 |\n| `resolution`   | `\"1K\"` \\| `\"2K\"` \\| `\"4K\"`                            | `\"1K\"`            | Output image resolution                                                       |\n| `aspectRatio`  | see below                                              | `\"1:1\"`           | Aspect ratio of the image                                                     |\n| `mode`         | `\"image\"` \\| `\"image_and_text\"`                        | `\"image\"`         | Return image only, or image with description (Google models only)             |\n| `background`   | `\"auto\"` \\| `\"transparent\"` \\| `\"opaque\"`              | `\"auto\"`          | What the image sits on. `\"transparent\"` needs a gpt-image model — see below   |\n| `thinking`     | `\"none\"` \\| `\"auto\"`                                   | `\"auto\"`          | Controls model thinking (Google models only)                                  |\n| `outputDir`    | `string`                                               | `\".\"`             | Directory where images will be saved                                          |\n| `inputImages`  | `string[]`                                             | -                 | File paths of images to send alongside the prompt (Google models, OpenAI gpt-image models via the images.edit endpoint, and Reve via v2 `references`) |\n\n#### Supported aspect ratios\n\n`1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `9:16`, `16:9`, `21:9`\n\n#### Transparent backgrounds\n\n`background: \"transparent\"` saves a PNG with an alpha channel, which is useful for\ncutting out a subject to place on a slide or over another image.\n\nOnly the OpenAI gpt-image models can do this. Asking any other model\n(`nano-banana-*`, `flux-2-*`, `reve-image`) for a transparent background **fails\nwith an error** rather than quietly returning an opaque image — the request is\nrejected before it is sent, so nothing is spent on it. Writing \"transparent\nbackground\" into the prompt does not help either: those providers have no\ntransparency mode at all.\n\n`\"opaque\"` forces a filled background on every provider that reads the field, and\n`\"auto\"` — the default — leaves the choice to the model, which is what this server\nhas always done.\n\n### Response\n\nReturns a JSON object:\n\n```json\n{\n  \"model\": \"gemini-3.1-flash-image-preview\",\n  \"savedFiles\": [\"/path/to/image-1.png\"],\n  \"settings\": {\n    \"resolution\": \"1K\",\n    \"aspectRatio\": \"9:16\",\n    \"mode\": \"image\",\n    \"background\": \"auto\"\n  },\n  \"description\": \"...\"\n}\n```\n\n> `description` is only present when `mode` is `\"image_and_text\"`.\n\n## Tool: `generate_video`\n\nAvailable when a Google key is configured. Generates one clip with audio and\nsaves it as an mp4.\n\n### Parameters\n\n| Parameter               | Type                                          | Default        | Description                                                                                       |\n| ----------------------- | --------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------- |\n| `prompt`                | `string` (1-32,000 chars)                     | -              | Subject, motion, camera, and any on-screen text spelled out exactly                               |\n| `model`                 | `\"gemini-omni-1.1-flash\"`                                | `\"gemini-omni-1.1-flash\"` | Video model to use                                                                                |\n| `durationSeconds`       | integer `3`–`10`                              | `5`            | Clip length. Cost scales with the second, and so does generation time (roughly 1 min for 5 s, 2 min for 10 s) |\n| `resolution`            | `\"360p\"` \\| `\"720p\"` \\| `\"1080p\"` \\| `\"4k\"` | `\"720p\"`       | Playback resolution. `360p` is the cheapest and fastest; `1080p` and `4k` are upscaled from 720p |\n| `aspectRatio`           | `\"16:9\"` \\| `\"9:16\"`                          | `\"16:9\"`       | Landscape or portrait                                                                             |\n| `outputDir`             | `string`                                      | `\".\"`          | Directory where the clip will be saved (same sandboxing as `generate_image`)                     |\n| `inputImages`           | `string[]`                                    | -              | Reference images sent ahead of the prompt: a first frame to animate, or subjects and styles to keep. Refer to them as `<IMAGE_REF_1>`, `<IMAGE_REF_2>`, … |\n| `previousInteractionId` | `string`                                      | -              | `interactionId` from an earlier result. Extends that clip instead of starting a new one; the prompt describes what happens next |\n\nThings worth knowing:\n\n- A single request is capped at 10 s by the model. To go longer, pass the\n  returned `interactionId` back as `previousInteractionId`; each extension adds\n  up to 10 s, and the whole clip is returned each time.\n- Text in the prompt is rendered on screen as written, including non-Latin\n  scripts, though Google only documents English as fully supported.\n- Clips are fetched through Google's file endpoint rather than inlined in the\n  JSON response, as the API documentation recommends above 4 MB. Expect one\n  extra request per generation.\n- 720p costs about $0.10 per second of output; there is no free tier for this model.\n\n### Response\n\n```json\n{\n  \"model\": \"gemini-omni-1.1-flash\",\n  \"savedFile\": \"/path/to/1788347054697-491db547.mp4\",\n  \"settings\": {\n    \"durationSeconds\": 5,\n    \"resolution\": \"720p\",\n    \"aspectRatio\": \"16:9\"\n  },\n  \"interactionId\": \"v1_...\",\n  \"description\": \"...\"\n}\n```\n\n> `description` is only present when the model returns text alongside the clip.\n\n## Use as a library\n\nBesides the standalone MCP server, this package can be embedded in another host —\nan app, or another MCP server that wants to expose image generation as its own tool.\n\n```ts\nimport { createRegistry, generateImageToDisk } from \"mcp-imagenate\";\n\n// Keys are passed in explicitly; nothing here reads process.env.\nconst registry = createRegistry({ openai: myOpenAIKey, google: myGoogleKey });\n\nif (registry.models.length === 0) {\n  throw new Error(\"No image provider is configured\");\n}\n\nconst outcome = await generateImageToDisk({\n  registry,\n  prompt: \"a calico cat asleep on a warm keyboard\",\n  model: registry.defaultModel!,\n  aspectRatio: \"16:9\",\n  outputDir: \"/somewhere/to/write\",\n  // outputBaseDir defaults to null, meaning no path sandboxing. Set it to a\n  // directory to confine both output and input paths within that directory.\n});\n\nconsole.log(outcome.savedFiles);\n```\n\n`generateImageToDisk` takes the same options as the tool, so `background:\n\"transparent\"` throws for a model that cannot deliver an alpha channel. Check\n`registry.resolve(model).supportsTransparentBackground` first if the model is not\none you chose yourself.\n\nThe library entry point never reads `process.env`, writes to stdio, or exits the\nprocess. To read keys from the conventional environment variables anyway, use the\n`keysFromEnv()` helper. The standalone server is available at `mcp-imagenate/server`.\n\n| Export | Purpose |\n| --- | --- |\n| `createRegistry(keys)` | Build a registry of the models available for the given keys |\n| `keysFromEnv(env?)` | Read provider keys from environment variables |\n| `generateImageToDisk(options)` | Generate images and write them to disk |\n| `createVideoRegistry(keys)` | Build a registry of the video models available for the given keys |\n| `generateVideoToDisk(options)` | Generate a clip and write it to disk |\n| `resolveOutputDir` / `resolveInputImagePath` | Path sandboxing helpers (opt-in) |\n\n## Security\n\n- **Path sandboxing**: When `NANO_BANANA_OUTPUT_DIR` is set, both output and input image paths are sandboxed within this directory. Symlinks that resolve outside the sandbox are rejected. For library embedders this is opt-in via `outputBaseDir`, since the host usually controls which paths reach the call.\n- **Input validation**: Input images are validated for format (PNG/JPEG/WEBP/GIF) and size (max 20 MB). Video durations outside the model's range are rejected before any request is sent.\n- **API key validation**: The server exits immediately if no API keys are configured. The library reports this as an empty registry instead, leaving the decision to the host.\n\n## License\n\nMIT\n",
  "bytes": 14899,
  "sha": "d668a7e7e3e225db2008ef6b906fb1cb756682eb12f61601e581837a1187980e",
  "repo_slug": "mimo-3/mcp-imagenate",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_mimo_3_mcp_imagenate_ab7860b5/readme"
}