media-gen-mcp
by AriOliv
README.md
# media-gen-mcp
MCP server for AI **image & video generation** — Google **Nano Banana** (Gemini image) and
**Veo 3.1** (video) — routed through a **LiteLLM / OpenAI-compatible gateway**.
Inspired by hosted media MCPs like Higgsfield's: video generation is **asynchronous with
polling**, and every asset comes back as a **public URL** (never inline base64), so agents can
pass results around cheaply.
## Tools
| Tool | What it does |
|---|---|
| `generate_image` | Text → PNG(s) with `nano-banana-pro` (Gemini 3 Pro Image, default) or `nano-banana-2` (Gemini 3.1 Flash Image — faster/cheaper). Synchronous, returns URLs. |
| `generate_video` | Text (± reference image) → async Veo job. `veo-3.1` (flagship, native audio, ~$0.40/s, default) or `veo-3.1-lite` (~$0.05/s for drafts). 4–8s, landscape or portrait. Returns a `video_id`. |
| `get_video` | Poll a job; on completion downloads the MP4 once, caches it, and returns its URL. |
| `list_generations` | Browse recent generations (id, kind, model, prompt, URL), newest first. |
## How it works
```
agent ──MCP──▶ media-gen-mcp ──OpenAI API──▶ LiteLLM ──▶ Gemini (Nano Banana / Veo)
│
└── saves PNG/MP4 to MEDIA_DIR, serves at /files/* → URL back to agent
```
- Images: `POST /v1/images/generations` (returns base64; decoded and stored here).
- Videos: `POST /v1/videos` → poll `GET /v1/videos/{id}` → `GET /v1/videos/{id}/content`.
The LiteLLM deployment must expose the four model aliases (`nano-banana-pro`,
`nano-banana-2`, `veo-3.1`, `veo-3.1-lite`) — see [LiteLLM image generation](https://docs.litellm.ai/docs/image_generation)
and video passthrough docs for the `gemini/` provider mappings.
## Quickstart (Docker)
```bash
cp .env.example .env # fill in LITELLM_BASE_URL, LITELLM_API_KEY, MCP_BEARER, PUBLIC_URL
docker compose up -d --build
curl -s localhost:8156/healthz
```
## Endpoints
| Path | Auth | Purpose |
|---|---|---|
| `POST /mcp` | `Authorization: Bearer $MCP_BEARER` | Streamable-HTTP MCP endpoint (stateless — safe for concurrent clients). |
| `GET /files/<name>` | none (unguessable names) | Generated assets, immutable-cached. |
| `GET /healthz` | none | Liveness probe. |
**The bearer is mandatory** — each generation spends real money, so `/mcp` must never be
exposed unauthenticated.
## Environment
| Var | Required | Description |
|---|---|---|
| `LITELLM_BASE_URL` | ✅ | LiteLLM / OpenAI-compatible gateway base URL. |
| `LITELLM_API_KEY` | ✅ | Key for the gateway — prefer a virtual key scoped to the media models with a budget. |
| `MCP_BEARER` | ✅ | Static bearer required on `/mcp` (≥24 chars; `openssl rand -base64 32`). |
| `PUBLIC_URL` | ✅ | Public base URL used to build the asset links returned by tools. |
| `MEDIA_DIR` | — | Asset storage dir (default `/data/media` in Docker). |
| `PORT` | — | Listen port (default 8000). |
## Connecting a client
Any MCP client that supports Streamable HTTP + bearer headers:
```json
{
"mcpServers": {
"media-gen": {
"url": "https://your-host/mcp",
"headers": { "Authorization": "Bearer <MCP_BEARER>" }
}
}
}
```
For local/stdio use (`claude mcp add media-gen -- node build/index.js`), set the same env
vars in `.env`.
## Development
```bash
npm install
npm run dev # HTTP entrypoint with hot reload
npm run typecheck
npm run smoke # initialize + tools/list against a running server
SMOKE_GENERATE=1 npm run smoke # also runs one real (paid) image generation
```
## License
MIT
TDQS
A4.4/5.0
Scored across 4 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: image generation (synchronous), video generation (asynchronous start), video polling/retrieval, and history listing. There is no overlap or ambiguity.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern with snake_case: generate_image, generate_video, get_video, list_generations. No deviations.
Tool Count4/5
Four tools is slightly on the low end but appropriate for a focused media generation service. Each tool earns its place and covers the core workflows.
Completeness4/5
The set covers image generation, video generation (with polling), and history listing. Minor gaps like a cancel tool for video jobs are not essential for a minimal viable surface.
Maintenance
ActivityStale
ResponsivenessNo issues