media-gen-mcp
MCP serverMediaThis app lets your AI create images and videos for you. Once added, it can generate visuals using OpenAI image and video models and Google's Veo video model. You describe what you want and your AI produces it.
Unavailable. This server has no hosted endpoint yet, so ahel can't serve it.
After adding the app, ask your AI to create an image or video and describe what you want it to show.
What your AI can do with it
- Generate images from a text description
- Create videos from a text description
- Produce videos with Google's Veo model
- Produce images and videos with OpenAI models
- Create media during a conversation
From the project's README
As published by strato-space/media-gen-mcp in README.md.
Media Gen MCP is a strict TypeScript Model Context Protocol (MCP) server for OpenAI Images (gpt-image-1.5, gpt-image-1), OpenAI Videos (Sora), and Google GenAI Videos (Veo): generate/edit images, create/remix video jobs, and fetch media from URLs or disk with smart resource_link vs inline image outputs and optional sharp processing. Production-focused (full strict typecheck, ESLint + Vitest CI). Works with fast-agent, Claude Desktop, ChatGPT, Cursor, VS Code, Windsurf, and any MCP-compatible client.
Design principle: spec-first, type-safe image tooling – strict OpenAI Images API + MCP compliance with fully static TypeScript types and flexible result placements/response formats for different clients.
- Generate images from text prompts using OpenAI's
gpt-image-1.5model (withgpt-image-1compatibility and DALL·E support planned in future versions). - Edit images (inpainting, outpainting, compositing) from 1 up to 16 images at once, with advanced prompt control.
- Generate videos via OpenAI Videos (
sora-2,sora-2-pro) with job create/remix/list/retrieve/delete and asset downloads. - Generate videos via Google GenAI (Veo) with operation polling and file-first downloads.
- Fetch & compress images from HTTP(S) URLs or local file paths with smart size/quality optimization.
- Fetch documents from HTTP(S) URLs or local file paths and return
resource_link/resourceoutputs. - Debug MCP output shapes with a
test-imagestool that mirrors production result placement (content,structuredContent,toplevel). - Integrates with: fast-agent, Windsurf, Claude Desktop, Cursor, VS Code, and any MCP-compatible client.
✨ Features
-
Strict MCP spec support
Tool outputs are first-classCallToolResultobjects from the latest MCP schema, including:contentitems (text,image,resource_link,resource), optionalstructuredContent, optional top-levelfiles, and theisErrorflag for failures. -
Full gpt-image-1.5 and sora-2/sora-2-pro parameters coverage (generate & edit)
openai-images-generatemirrors the OpenAI ImagescreateAPI forgpt-image-1.5(andgpt-image-1) (background, moderation, size, quality, output_format, output_compression,n,user, etc.).openai-images-editmirrors the OpenAI ImagescreateEditAPI forgpt-image-1.5(andgpt-image-1) (image, mask,n, quality, size,user).
-
OpenAI Videos (Sora) job tooling (create / remix / list / retrieve / delete / content)
openai-videos-createmirrorsvideos/createand can optionally wait for completion.openai-videos-remixmirrorsvideos/remix.openai-videos-listmirrorsvideos/list.openai-videos-retrievemirrorsvideos/retrieve.openai-videos-deletemirrorsvideos/delete.openai-videos-retrieve-contentmirrorsvideos/contentand downloadsvideo/thumbnail/spritesheetassets to disk, returning MCPresource_link(default) or embeddedresourceblocks (viatool_result).
-
Google GenAI (Veo) operations + downloads (generate / retrieve operation / retrieve content)
google-videos-generatestarts a long-running operation (ai.models.generateVideos) and can optionally wait for completion and download.mp4outputs. Veo model referencegoogle-videos-retrieve-operationpolls an existing operation.google-videos-retrieve-contentdownloads an.mp4from a completed operation, returning MCPresource_link(default) or embeddedresourceblocks (viatool_result).
-
Fetch and process images from URLs or files
fetch-imagestool loads images from HTTP(S) URLs or local file paths with optional, user-controlled compression (disabled by default). Supports parallel processing of up to 20 images. -
Fetch videos from URLs or files
fetch-videostool lists local videos or downloads remote video URLs to disk and returns MCPresource_link(default) or embeddedresourceblocks (viatool_result). -
Fetch documents from URLs or files
fetch-documenttool downloads remote files or reuses local paths and returns MCPresource_link(default) or embeddedresourceblocks (viatool_result). -
Mix and edit up to 16 images
openai-images-editacceptsimageas a single string or an array of 1–16 file paths/base64 strings, matching the OpenAI spec for GPT Image models (gpt-image-1.5,gpt-image-1) image edits. -
Smart image compression
Built-in compression using sharp — iteratively reduces quality and dimensions to fit MCP payload limits while maintaining visual quality. -
Resource-aware file output with
resource_link- Automatic switch from inline base64 to
filewhen the total response size exceeds a safe threshold. - Outputs are written to disk using
output_<time_t>_media-gen__<tool>_<id>.<ext>filenames (images/documents use a generated UUID; videos use the OpenAIvideo_id) and exposed to MCP clients viacontent[]depending ontool_result(resource_link/imagefor images,resource_link/resourcefor video/document downloads).
- Automatic switch from inline base64 to
-
Built-in test-images tool for MCP client debugging
test-imagesreads sample images from a configured directory and returns them using the same result-building logic as production tools. Usetool_resultandresponse_formatparameters to test how different MCP clients handlecontent[]andstructuredContent. -
Structured MCP error handling
All tool errors (validation, OpenAI API failures, I/O) are returned as MCP errors withisError: trueandcontent: [{ type: "text", text: <error message> }], making failures easy to parse and surface in MCP clients.
🚀 Installation
git clone https://github.com/strato-space/media-gen-mcp.git
cd media-gen-mcp
npm install
npm run build
Build modes:
npm run build– strict TypeScript build with all strict flags enabled, includingskipLibCheck: false. Incremental builds via.tsbuildinfo(~2-3s on warm cache).npm run esbuild– fast bundling via esbuild (no type checking, useful for rapid iteration).
Development mode (no build required)
For development or when TypeScript compilation fails due to memory constraints:
npm run dev # Uses tsx to run TypeScript directly
Quality checks
npm run lint # ESLint with typescript-eslint
npm run typecheck # Strict tsc --noEmit
npm run test # Unit tests (vitest)
npm run test:watch # Watch mode for TDD
npm run ci # lint + typecheck + test
Unit tests
The project uses vitest for unit testing. Tests are located in test/.
Covered modules:
| Module | Tests | Description |
|---|---|---|
compression | 12 | Image format detection, buffer processing, file I/O |
helpers | 31 | URL/path validation, output resolution, result placement, resource links |
env | 19 | Configuration parsing, env validation, defaults |
logger | 10 | Structured logging + truncation safety |
pricing | 5 | Sora pricing estimate helpers |
schemas | 69 | Zod schema validation for all tools, type inference |
fetch-images (integration) | 3 | End-to-end MCP tool call behavior |
fetch-videos (integration) | 3 | End-to-end MCP tool call behavior |
Test categories:
- compression —
isCompressionAvailable,detectImageFormat,processBufferWithCompression,readAndProcessImage - helpers —
isHttpUrl,isAbsolutePath,isBase64Image,ensureDirectoryWritable,resolveOutputPath,getResultPlacement,buildResourceLinks - env — config loading and validation for
MEDIA_GEN_*/MEDIA_GEN_MCP_*settings - logger — truncation and error formatting behavior
- schemas — validation for
openai-images-*,openai-videos-*,fetch-images,fetch-videos,test-imagesinputs, boundary testing (prompt length, image count limits, path validation)
npm run test
# ✓ test/compression.test.ts (12 tests)
# ✓ test/helpers.test.ts (31 tests)
# ✓ test/env.test.ts (19 tests)
# ✓ test/logger.test.ts (10 tests)
# ✓ test/pricing.test.ts (5 tests)
# ✓ test/schemas.test.ts (69 tests)
# ✓ test/fetch-images.integration.test.ts (3 tests)
# ✓ test/fetch-videos.integration.test.ts (3 tests)
# Tests: 152 passed
Run directly via npx (no local clone)
You can also run the server straight from a remote repo using npx:
npx -y github:strato-space/media-gen-mcp --env-file /path/to/media-gen.env
The --env-file argument tells the server which env file to load (e.g. when you keep secrets outside the cloned directory). The file should contain OPENAI_API_KEY, optional Azure variables, and any MEDIA_GEN_MCP_* settings.
secrets.yaml (optional)
You can keep API keys (and optional Google Vertex AI settings) in a secrets.yaml file (compatible with the fast-agent secrets template):
openai:
api_key: <your-api-key-here>
anthropic:
api_key: <your-api-key-here>
google:
api_key: <your-api-key-here>
vertex_ai:
enabled: true
project_id: your-gcp-project-id
location: europe-west4
media-gen-mcp loads secrets.yaml from the current working directory (or from --secrets-file /path/to/secrets.yaml) and applies it to env vars; values in secrets.yaml override env, and <your-api-key-here> placeholders are ignored.
⚡ Quick start (fast-agent & Windsurf)
fast-agent
In fast-agent, MCP servers are configured in fastagent.config.yaml under the mcp.servers section (see the fast-agent docs).
To add media-gen-mcp from GitHub via npx as an MCP server:
# fastagent.config.yaml
mcp:
servers:
# your existing servers (e.g. fetch, filesystem, huggingface, ...)
media-gen-mcp:
command: "npx"
args: ["-y", "github:strato-space/media-gen-mcp", "--env-file", "/path/to/media-gen.env"]
Put OPENAI_API_KEY and other settings into media-gen.env (see .env.sample in this repo).
Windsurf
Add an MCP server that runs media-gen-mcp from GitHub via npx using the JSON format below (similar to Claude Desktop / VS Code):
{
"mcpServers": {
"media-gen-mcp": {
"command": "npx",
"args": ["-y", "github:strato-space/media-gen-mcp", "--env-file", "/path/to/media-gen.env"]
}
}
}
🔑 Configuration
Add to your MCP client config (fast-agent, Windsurf, Claude Desktop, Cursor, VS Code):
{
"mcpServers": {
"media-gen-mcp": {
"command": "npx",
"args": ["-y", "github:strato-space/media-gen-mcp"],
"env": { "OPENAI_API_KEY": "sk-..." }
}
}
}
Also supports Azure deployments:
{
"mcpServers": {
"media-gen-mcp": {
"command": "npx",
"args": ["-y", "github:strato-space/media-gen-mcp"],
"env": {
// "AZURE_OPENAI_API_KEY": "sk-...",
// "AZURE_OPENAI_ENDPOINT": "my.endpoint.com",
"OPENAI_API_VERSION": "2024-12-01-preview"
}
}
}
}
Environment variables:
- Set
OPENAI_API_KEY(and optionallyAZURE_OPENAI_API_KEY,AZURE_OPENAI_ENDPOINT,OPENAI_API_VERSION) in the environment of the process that runsnode dist/index.js(shell, systemd unit, Docker env, etc.). - The server will optionally load a local
.envfile from its working directory if present (it does not override already-set environment variables). - You can also pass
--env-file /path/to/envwhen starting the server (including vianpx); this file is loaded viadotenvbefore tools run, again without overriding already-set variables.
Logging and base64 truncation
To avoid flooding logs with huge image payloads, the built-in logger applies a
log-only sanitizer to structured data passed to log.debug/info/warn/error:
- Truncates configured string fields (e.g.
b64_json,base64, stringdata,image_url) to a short preview controlled byLOG_TRUNCATE_DATA_MAX(default: 64 characters). The list of keys defaults toLOG_SANITIZE_KEYSinsidesrc/lib/logger.tsand can be overridden viaMEDIA_GEN_MCP_LOG_SANITIZE_KEYS(comma-separated list of field names). - Sanitization is applied only to log serialization; tool results returned to MCP clients are never modified.
Control via environment:
MEDIA_GEN_MCP_LOG_SANITIZE_IMAGES(default:true)1,true,yes,on– enable truncation (default behaviour).0,false,no,off– disable truncation and log full payloads.
Field list and limits are configured in src/lib/logger.ts via
LOG_SANITIZE_KEYS and LOG_TRUNCATE_DATA_MAX.
Security and local file access
- Allowed directories: All tools are restricted to paths matching
MEDIA_GEN_DIRS. If unset, defaults to/tmp/media-gen-mcp(or%TEMP%/media-gen-mcpon Windows). - Test samples:
MEDIA_GEN_MCP_TEST_SAMPLE_DIRadds a directory to the allowlist and enables thetest-imagestool. - Local reads:
fetch-imagesandfetch-documentaccept file paths (absolute or relative). Relative paths are resolved against the firstMEDIA_GEN_DIRSentry and must still match an allowed pattern. - Remote reads: HTTP(S) fetches are filtered by
MEDIA_GEN_URLSpatterns. Empty = allow all. - Writes:
openai-images-generate,openai-images-edit,fetch-images,fetch-videos, andfetch-documentwrite under the first entry ofMEDIA_GEN_DIRS.test-imagesis read-only and does not create new files.
Glob patterns
Both MEDIA_GEN_DIRS and MEDIA_GEN_URLS support glob wildcards:
| Pattern | Matches | Example |
|---|---|---|
* | Any single segment (no /) | /home/*/media/ matches /home/user1/media/ |
** | Any number of segments | /data/**/images/ matches /data/a/b/images/ |
URL examples:
MEDIA_GEN_URLS=https://*.cdn.example.com/,https://storage.example.com/**/assets/
Path examples:
MEDIA_GEN_DIRS=/home/*/media-gen/output/,/data/**/images/
⚠️ Warning: Trailing wildcards without a delimiter (e.g., /home/user/* or https://cdn.com/**) expose entire subtrees and trigger a console warning at startup.
Recommended mitigations
- Run under a dedicated OS user with access only to allowed directories.
- Keep allowlists minimal. Avoid
*in home directories or system paths. - Use explicit
MEDIA_GEN_URLSprefixes for remote fetches. - Monitor allowed directories via OS ACLs or backups.
Tool Result Parameters: tool_result and response_format
Image tools (openai-images-*, fetch-images, test-images) support two parameters that control the shape of the MCP tool result:
| Parameter | Values | Default | Description |
|---|---|---|---|
tool_result | resource_link, image | resource_link | Controls content[] shape |
response_format | url, path, b64_json | url | Controls structuredContent shape (OpenAI ImagesResponse format) |
Video/document download tools (openai-videos-create / openai-videos-remix when downloading, openai-videos-retrieve-content, google-videos-generate when downloading, google-videos-retrieve-content, fetch-videos, fetch-document) support:
| Parameter | Values | Default | Description |
|---|---|---|---|
tool_result | resource_link, resource | resource_link | Controls content[] shape |
Google video tools (google-videos-*) also support:
| Parameter | Values | Default | Description |
|---|---|---|---|
response_format | url, b64_json | url | Controls structuredContent.response.generatedVideos[].video shape (uri vs videoBytes) |
tool_result — controls content[]
- Images (
openai-images-*,fetch-images,test-images)resource_link(default): EmitsResourceLinkitems withfile://orhttps://URIsimage: Emits base64ImageContentblocks
- Videos (tools that download video data)
resource_link(default): EmitsResourceLinkitems withfile://orhttps://URIsresource: EmitsEmbeddedResourceblocks with base64resource.blob
- Documents (
fetch-document)resource_link(default): EmitsResourceLinkitems withfile://orhttps://URIsresource: EmitsEmbeddedResourceblocks with base64resource.blob
response_format — controls structuredContent
For OpenAI images, structuredContent always contains an OpenAI ImagesResponse-style object:
{
"created": 1234567890,
"data": [
{ "url": "https://..." } // or { "path": "/abs/path.png" } / { "b64_json": "..." } depending on response_format
]
}
url(default):data[].urlcontains file URLspath:data[].pathcontains local filesystem pathsb64_json:data[].b64_jsoncontains base64-encoded image data
For Google videos, response_format controls whether structuredContent.response.generatedVideos[].video prefers:
url(default):video.uri(and stripsvideo.videoBytes)b64_json:video.videoBytes(and stripsvideo.uri)
Backward Compatibility (MCP 5.2.6)
Per MCP spec 5.2.6, a TextContent block with serialized JSON (always using URLs in data[]) is also included in content[] for backward compatibility with clients that don't support structuredContent.
Example tool result structure:
{
"content": [
// ResourceLink or ImageContent based on tool_result
{ "type": "resource_link", "uri": "https://...", "name": "image.png", "mimeType": "image/png" },
// Serialized JSON for backward compatibility (MCP 5.2.6)
{ "type": "text", "text": "{ \"created\": 1234567890, \"data\": [{ \"url\": \"https://...\" }] }" }
],
"structuredContent": {
"created": 1234567890,
"data": [{ "url": "https://..." }]
}
}
ChatGPT MCP client behavior (chatgpt.com, as of 2025-12-01):
- ChatGPT currently ignores
content[]image data in favor ofstructuredContent. - For ChatGPT, use
response_format: "url"and configure the firstMEDIA_GEN_MCP_URL_PREFIXESentry as a public HTTPS prefix (for exampleMEDIA_GEN_MCP_URL_PREFIXES=https://media-gen.example.com/media).
For Anthropic clients (Claude Desktop, etc.), the default configuration works well.
Network access via mcp-proxy (SSE)
For networked SSE access you can front media-gen-mcp with mcp-proxy or its equivalent. This setup has been tested with the TypeScript SSE proxy implementation punkpeye/mcp-proxy.
For example, a one-line command looks like:
mcp-proxy --host=0.0.0.0 --port=99 --server=sse --sseEndpoint=/ --shell 'npx -y github:strato-space/media-gen-mcp --env-file /path/to/media-gen.env'
In production you would typically wire this up via a systemd template unit that loads PORT/SHELL_CMD from an EnvironmentFile= (see server/mcp/mcp@.service style setups).
🛠 Tool signatures
openai-images-generate
Arguments (input schema):
prompt(string, required)- Text prompt describing the desired image.
- Max length: 32,000 characters.
background("transparent" | "opaque" | "auto", optional)- Background handling mode.
- If
backgroundis"transparent", thenoutput_formatmust be"png"or"webp".
model("gpt-image-1.5" | "gpt-image-1", optional, default: "gpt-image-1.5")moderation("auto" | "low", optional)- Content moderation behavior, passed through to the Images API.
n(integer, optional)- Number of images to generate.
- Min: 1, Max: 10.
output_compression(integer, optional)- Compression level (0–100).
- Only applied when
output_formatis"jpeg"or"webp".
output_format("png" | "jpeg" | "webp", optional)- Output image format.
- If omitted, the server treats output as PNG semantics.
quality("auto" | "high" | "medium" | "low", default: "high")size("1024x1024" | "1536x1024" | "1024x1536" | "auto", default: "1024x1536")user(string, optional)- User identifier forwarded to OpenAI for monitoring.
response_format("url" | "path" | "b64_json", default: "url")- Response format (aligned with OpenAI Images API):
"url": file/URL-based output (resource_link items,image_urlfields,data[].urlinapiplacement)."path": local filesystem paths indata[].path(for local skill workflows)."b64_json": inline base64 image data (image content,data[].b64_jsoninapiplacement).
tool_result("resource_link" | "image", default: "resource_link")- Controls
content[]shape:"resource_link"emits ResourceLink items (file/URL-based)"image"emits base64 ImageContent blocks
- Controls
- Response format (aligned with OpenAI Images API):
Behavior notes:
Shortened here. Read the whole README on GitHub.
Signals
- GitHub stars
- 9
- Forks
- 4
- Last commit
- Jan 2026
Advanced
- Delivery
- media-gen-mcp MCP server → your ahel gateway (mcp.ahel.ai) → every connected AI client.
- Catalog kind
- mcp-server
- Gateway key
io-github-strato-space-media-gen-mcp- Source
- github.com/strato-space/media-gen-mcp