media-gen-mcp

MCP serverMedia

This 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.5 model (with gpt-image-1 compatibility 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/resource outputs.
  • Debug MCP output shapes with a test-images tool 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-class CallToolResult objects from the latest MCP schema, including: content items (text, image, resource_link, resource), optional structuredContent, optional top-level files, and the isError flag for failures.

  • Full gpt-image-1.5 and sora-2/sora-2-pro parameters coverage (generate & edit)

    • openai-images-generate mirrors the OpenAI Images create API for gpt-image-1.5 (and gpt-image-1) (background, moderation, size, quality, output_format, output_compression, n, user, etc.).
    • openai-images-edit mirrors the OpenAI Images createEdit API for gpt-image-1.5 (and gpt-image-1) (image, mask, n, quality, size, user).
  • OpenAI Videos (Sora) job tooling (create / remix / list / retrieve / delete / content)

    • openai-videos-create mirrors videos/create and can optionally wait for completion.
    • openai-videos-remix mirrors videos/remix.
    • openai-videos-list mirrors videos/list.
    • openai-videos-retrieve mirrors videos/retrieve.
    • openai-videos-delete mirrors videos/delete.
    • openai-videos-retrieve-content mirrors videos/content and downloads video / thumbnail / spritesheet assets to disk, returning MCP resource_link (default) or embedded resource blocks (via tool_result).
  • Google GenAI (Veo) operations + downloads (generate / retrieve operation / retrieve content)

    • google-videos-generate starts a long-running operation (ai.models.generateVideos) and can optionally wait for completion and download .mp4 outputs. Veo model reference
    • google-videos-retrieve-operation polls an existing operation.
    • google-videos-retrieve-content downloads an .mp4 from a completed operation, returning MCP resource_link (default) or embedded resource blocks (via tool_result).
  • Fetch and process images from URLs or files
    fetch-images tool 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-videos tool lists local videos or downloads remote video URLs to disk and returns MCP resource_link (default) or embedded resource blocks (via tool_result).

  • Fetch documents from URLs or files
    fetch-document tool downloads remote files or reuses local paths and returns MCP resource_link (default) or embedded resource blocks (via tool_result).

  • Mix and edit up to 16 images
    openai-images-edit accepts image as 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 file when 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 OpenAI video_id) and exposed to MCP clients via content[] depending on tool_result (resource_link/image for images, resource_link/resource for video/document downloads).
  • Built-in test-images tool for MCP client debugging
    test-images reads sample images from a configured directory and returns them using the same result-building logic as production tools. Use tool_result and response_format parameters to test how different MCP clients handle content[] and structuredContent.

  • Structured MCP error handling
    All tool errors (validation, OpenAI API failures, I/O) are returned as MCP errors with isError: true and content: [{ 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, including skipLibCheck: 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:

ModuleTestsDescription
compression12Image format detection, buffer processing, file I/O
helpers31URL/path validation, output resolution, result placement, resource links
env19Configuration parsing, env validation, defaults
logger10Structured logging + truncation safety
pricing5Sora pricing estimate helpers
schemas69Zod schema validation for all tools, type inference
fetch-images (integration)3End-to-end MCP tool call behavior
fetch-videos (integration)3End-to-end MCP tool call behavior

Test categories:

  • compressionisCompressionAvailable, detectImageFormat, processBufferWithCompression, readAndProcessImage
  • helpersisHttpUrl, 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-images inputs, 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 optionally AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, OPENAI_API_VERSION) in the environment of the process that runs node dist/index.js (shell, systemd unit, Docker env, etc.).
  • The server will optionally load a local .env file from its working directory if present (it does not override already-set environment variables).
  • You can also pass --env-file /path/to/env when starting the server (including via npx); this file is loaded via dotenv before 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, string data, image_url) to a short preview controlled by LOG_TRUNCATE_DATA_MAX (default: 64 characters). The list of keys defaults to LOG_SANITIZE_KEYS inside src/lib/logger.ts and can be overridden via MEDIA_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-mcp on Windows).
  • Test samples: MEDIA_GEN_MCP_TEST_SAMPLE_DIR adds a directory to the allowlist and enables the test-images tool.
  • Local reads: fetch-images and fetch-document accept file paths (absolute or relative). Relative paths are resolved against the first MEDIA_GEN_DIRS entry and must still match an allowed pattern.
  • Remote reads: HTTP(S) fetches are filtered by MEDIA_GEN_URLS patterns. Empty = allow all.
  • Writes: openai-images-generate, openai-images-edit, fetch-images, fetch-videos, and fetch-document write under the first entry of MEDIA_GEN_DIRS. test-images is read-only and does not create new files.
Glob patterns

Both MEDIA_GEN_DIRS and MEDIA_GEN_URLS support glob wildcards:

PatternMatchesExample
*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
  1. Run under a dedicated OS user with access only to allowed directories.
  2. Keep allowlists minimal. Avoid * in home directories or system paths.
  3. Use explicit MEDIA_GEN_URLS prefixes for remote fetches.
  4. 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:

ParameterValuesDefaultDescription
tool_resultresource_link, imageresource_linkControls content[] shape
response_formaturl, path, b64_jsonurlControls 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:

ParameterValuesDefaultDescription
tool_resultresource_link, resourceresource_linkControls content[] shape

Google video tools (google-videos-*) also support:

ParameterValuesDefaultDescription
response_formaturl, b64_jsonurlControls structuredContent.response.generatedVideos[].video shape (uri vs videoBytes)
tool_result — controls content[]
  • Images (openai-images-*, fetch-images, test-images)
    • resource_link (default): Emits ResourceLink items with file:// or https:// URIs
    • image: Emits base64 ImageContent blocks
  • Videos (tools that download video data)
    • resource_link (default): Emits ResourceLink items with file:// or https:// URIs
    • resource: Emits EmbeddedResource blocks with base64 resource.blob
  • Documents (fetch-document)
    • resource_link (default): Emits ResourceLink items with file:// or https:// URIs
    • resource: Emits EmbeddedResource blocks with base64 resource.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[].url contains file URLs
  • path: data[].path contains local filesystem paths
  • b64_json: data[].b64_json contains base64-encoded image data

For Google videos, response_format controls whether structuredContent.response.generatedVideos[].video prefers:

  • url (default): video.uri (and strips video.videoBytes)
  • b64_json: video.videoBytes (and strips video.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 of structuredContent.
  • For ChatGPT, use response_format: "url" and configure the first MEDIA_GEN_MCP_URL_PREFIXES entry as a public HTTPS prefix (for example MEDIA_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 background is "transparent", then output_format must 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_format is "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_url fields, data[].url in api placement).
      • "path": local filesystem paths in data[].path (for local skill workflows).
      • "b64_json": inline base64 image data (image content, data[].b64_json in api placement).
    • tool_result ("resource_link" | "image", default: "resource_link")
      • Controls content[] shape:
        • "resource_link" emits ResourceLink items (file/URL-based)
        • "image" emits base64 ImageContent blocks

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