Skip to main content
Glama

media-gen-mcp


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)

  • Google GenAI (Veo) operations + downloads (generate / retrieve operation / retrieve content)

  • 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.


Related MCP server: imagegen-mcp

🚀 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:

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:

  • 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:

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.

  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:

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): 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:

  • The server uses OpenAI gpt-image-1.5 by default (set model: "gpt-image-1" for legacy behavior).

  • If the total size of all base64 images would exceed the configured payload threshold (default ~50MB via MCP_MAX_CONTENT_BYTES), the server automatically switches the effective output mode to file/URL-based and saves images to the first entry of MEDIA_GEN_DIRS (default: /tmp/media-gen-mcp).

  • Even when you explicitly request response_format: "b64_json", the server still writes the files to disk (for static hosting, caching, or later reuse). Exposure of file paths / URLs in the tool result then depends on MEDIA_GEN_MCP_RESULT_PLACEMENT and per-call result_placement (see section below).

Output (MCP CallToolResult, when placement includes "content"):

  • When the effective output mode is "base64":

    • content is an array that may contain:

      • image items:

        • { type: "image", data: <base64 string>, mimeType: <"image/png" | "image/jpeg" | "image/webp"> }

      • optional text items with revised prompts returned by the Images API (for models that support it, e.g. DALL·E 3):

        • { type: "text", text: <revised_prompt string> }

  • When the effective output mode is "file":

    • content contains one resource_link item per file, plus the same optional text items with revised prompts:

      • { type: "resource_link", uri: "file:///absolute-path-1.png", name: "absolute-path-1.png", mimeType: <image mime> }

    • For gpt-image-1.5 and gpt-image-1, an additional text line is included with a pricing estimate (based on structuredContent.usage), and structuredContent.pricing contains the full pricing breakdown.

When result_placement includes "api", openai-images-generate instead returns an OpenAI Images API-like object without MCP wrappers:

{
  "created": 1764599500,
  "data": [
    { "b64_json": "..." } // or { "url": "https://.../media/file.png" } when output: "file"
  ],
  "background": "opaque",
  "output_format": "png",
  "size": "1024x1024",
  "quality": "high"
}

openai-images-edit

Arguments (input schema):

  • image (string or string[], required)

    • Either a single absolute path to an image file (.png, .jpg, .jpeg, .webp), a base64-encoded image string (optionally as a data:image/...;base64,... URL), or an HTTP(S) URL pointing to a publicly accessible image, or an array of 1–16 such strings (for multi-image editing).

    • When an HTTP(S) URL is provided, the server fetches the image and converts it to base64 before sending to OpenAI.

  • prompt (string, required)

    • Text description of the desired edit.

    • Max length: 32,000 characters.

  • mask (string, optional)

    • Absolute path, base64 string, or HTTP(S) URL for a mask image (PNG < 4MB, same dimensions as the source image). Transparent areas mark regions to edit.

  • model ("gpt-image-1.5" | "gpt-image-1", optional, default: "gpt-image-1.5")

  • n (integer, optional)

    • Number of images to generate.

    • Min: 1, Max: 10.

  • 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:

  • The server accepts image and mask as absolute paths, base64/data URLs, or HTTP(S) URLs.

  • When an HTTP(S) URL is provided, the server fetches the image and converts it to a base64 data URL before calling OpenAI.

  • For edits, the server always returns PNG semantics (mime type image/png) when emitting images.

Output (MCP CallToolResult):

  • When the effective output mode is "base64":

    • content is an array that may contain:

      • image items:

        • { type: "image", data: <base64 string>, mimeType: "image/png" }

      • optional text items with revised prompts (when the underlying model returns them):

        • { type: "text", text: <revised_prompt string> }

  • When the effective output mode is "file":

    • content contains one resource_link item per file, plus the same optional text items with revised prompts:

      • { type: "resource_link", uri: "file:///absolute-path-1.png", name: "absolute-path-1.png", mimeType: "image/png" }

    • For gpt-image-1.5 and gpt-image-1, an additional text line is included with a pricing estimate (based on structuredContent.usage), and structuredContent.pricing contains the full pricing breakdown.

When result_placement includes "api", openai-images-edit follows the same raw API format as openai-images-generate (top-level created, data[], background, output_format, size, quality with b64_json for base64 output or url for file output).

Error handling (both tools):

  • On errors inside the tool handler (validation, OpenAI API failures, I/O, etc.), the server returns a CallToolResult marked as an error:

    • isError: true

    • content: [{ type: "text", text: <error message string> }]

  • The error message text is taken directly from the underlying exception message, without additional commentary from the server, while full details are logged to the server console.

openai-videos-create

Create a video generation job using the OpenAI Videos API (videos.create).

Arguments (input schema):

  • prompt (string, required) — text prompt describing the video (max 32K chars).

  • input_reference (string, optional) — optional image reference (HTTP(S) URL, base64/data URL, or file path).

  • input_reference_fit ("match" | "cover" | "contain" | "stretch", default: "contain")

    • How to fit input_reference to the requested video size:

      • match: require exact dimensions (fails fast on mismatch)

      • cover: resize + center-crop to fill

      • contain: resize + pad/letterbox to fit (default)

      • stretch: resize with distortion

  • input_reference_background ("blur" | "black" | "white" | "#RRGGBB" | "#RRGGBBAA", default: "blur")

    • Padding background used when input_reference_fit="contain".

  • model ("sora-2" | "sora-2-pro", default: "sora-2-pro")

  • seconds ("4" | "8" | "12", optional)

  • size ("720x1280" | "1280x720" | "1024x1792" | "1792x1024", optional)

    • 1024x1792 and 1792x1024 require sora-2-pro.

    • If input_reference is omitted and size is omitted, the API default is used.

  • wait_for_completion (boolean, default: true)

    • When true, the server polls openai-videos-retrieve until completed or failed (or timeout), then downloads assets.

  • timeout_ms (integer, default: 900000)

  • poll_interval_ms (integer, default: 2000)

  • download_variants (string[], default: ["video"])

    • Allowed values: "video" | "thumbnail" | "spritesheet".

  • tool_result ("resource_link" | "resource", default: "resource_link")

    • Controls content[] shape for downloaded assets:

      • "resource_link" emits ResourceLink items (file/URL-based)

      • "resource" emits EmbeddedResource blocks with base64 resource.blob

Output (MCP CallToolResult):

  • structuredContent: OpenAI Video object (job metadata; final state when wait_for_completion=true).

  • content: includes resource_link (default) or embedded resource blocks for downloaded assets (when requested) and text blocks with JSON.

    • Includes a summary JSON block: { "video_id": "...", "pricing": { "currency": "USD", "model": "...", "size": "...", "seconds": 4, "price": 0.1, "cost": 0.4 } | null } (and when waiting: { "video_id": "...", "assets": [...], "pricing": ... }).

openai-videos-remix

Create a remix job from an existing video_id (videos.remix).

Arguments (input schema):

  • video_id (string, required)

  • prompt (string, required)

  • wait_for_completion, timeout_ms, poll_interval_ms, download_variants, tool_result — same semantics as openai-videos-create (default wait is true).

openai-videos-list

List video jobs (videos.list).

Arguments (input schema):

  • after (string, optional) — cursor (video id) to list after.

  • limit (integer, optional)

  • order ("asc" | "desc", optional)

Output:

  • structuredContent: OpenAI list response shape { data, has_more, last_id }.

  • content: a text block with serialized JSON.

openai-videos-retrieve

Retrieve job status (videos.retrieve).

  • video_id (string, required)

openai-videos-delete

Delete a video job (videos.delete).

  • video_id (string, required)

openai-videos-retrieve-content

Retrieve an asset for a completed job (videos.downloadContent, REST GET /videos/{video_id}/content), write it under allowed MEDIA_GEN_DIRS, and return MCP resource_link (default) or embedded resource blocks (via tool_result).

Arguments (input schema):

  • video_id (string, required)

  • variant ("video" | "thumbnail" | "spritesheet", default: "video")

  • tool_result ("resource_link" | "resource", default: "resource_link")

Output (MCP CallToolResult):

  • structuredContent: OpenAI Video object.

  • content: a resource_link (or embedded resource), a summary JSON block { video_id, variant, uri, pricing }, plus the full video JSON.

google-videos-generate

Create a Google video generation operation using the Google GenAI SDK (@google/genai) ai.models.generateVideos.

Arguments (input schema):

  • prompt (string, optional)

  • input_reference (string, optional) — image-to-video input (HTTP(S) URL, base64/data URL, or file path under MEDIA_GEN_DIRS)

  • input_reference_mime_type (string, optional) — override for input_reference MIME type (must be image/*)

  • input_video_reference (string, optional) — video-extension input (HTTP(S) URL or file path under MEDIA_GEN_DIRS; mutually exclusive with input_reference)

  • model (string, default: "veo-3.1-generate-001")

  • number_of_videos (integer, default: 1)

  • aspect_ratio ("16:9" | "9:16", optional)

  • duration_seconds (integer, optional)

    • Veo 2 models: 5–8 seconds (default: 8)

    • Veo 3 models: 4, 6, or 8 seconds (default: 8)

    • When using referenceImages: 8 seconds

  • person_generation ("DONT_ALLOW" | "ALLOW_ADULT" | "ALLOW_ALL", optional)

  • wait_for_completion (boolean, default: true)

  • timeout_ms (integer, default: 900000)

  • poll_interval_ms (integer, default: 10000)

  • download_when_done (boolean, optional; defaults to true when waiting)

  • tool_result ("resource_link" | "resource", default: "resource_link")

    • Controls content[] shape when downloading generated videos.

  • response_format ("url" | "b64_json", default: "url")

    • Controls structuredContent.response.generatedVideos[].video fields:

      • "url" prefers video.uri (and strips video.videoBytes)

      • "b64_json" prefers video.videoBytes (and strips video.uri)

Requirements:

  • Gemini Developer API: set GEMINI_API_KEY (or GOOGLE_API_KEY), or google.api_key in secrets.yaml.

  • Vertex AI: set GOOGLE_GENAI_USE_VERTEXAI=true, GOOGLE_CLOUD_PROJECT, and GOOGLE_CLOUD_LOCATION (or google.vertex_ai.* in secrets.yaml).

Output:

  • structuredContent: Google operation object (includes name, done, and response.generatedVideos[] when available).

  • content: status text, optional .mp4 resource_link (default) or embedded resource blocks (when downloaded), plus JSON text blocks for compatibility.

google-videos-retrieve-operation

Retrieve/poll an existing Google video operation (ai.operations.getVideosOperation).

  • operation_name (string, required)

  • response_format ("url" | "b64_json", default: "url")

Output:

  • structuredContent: Google operation object.

  • content: JSON text blocks with a short summary + the full operation.

google-videos-retrieve-content

Download .mp4 content for a completed operation and return file-first MCP resource_link (default) or embedded resource blocks (via tool_result).

  • operation_name (string, required)

  • index (integer, default: 0) — selects response.generatedVideos[index]

  • tool_result ("resource_link" | "resource", default: "resource_link")

  • response_format ("url" | "b64_json", default: "url")

Recommended workflow:

  1. Call google-videos-generate with wait_for_completion=true (default) to get the completed operation and downloads; set to false only if you need the operation id immediately.

  2. Poll google-videos-retrieve-operation until done=true.

  3. Call google-videos-retrieve-content to download an .mp4 and receive a resource_link (or embedded resource).

fetch-images

Fetch and process images from URLs or local file paths with optional compression.

Arguments (input schema):

  • sources (string[], optional)

    • Array of image sources: HTTP(S) URLs or file paths (absolute or relative to the first MEDIA_GEN_DIRS entry).

    • Min: 1, Max: 20 images.

    • Mutually exclusive with ids and n.

  • ids (string[], optional)

    • Array of image IDs to fetch by local filename match under the primary MEDIA_GEN_DIRS[0] directory.

    • IDs must be safe ([A-Za-z0-9_-] only; no .., *, ?, slashes).

    • Matches filenames containing _{id}_ or _{id}. (supports both single outputs and multi-output suffixes like _1.png).

    • When ids is used, compression and file are not supported (no new files are created).

    • Mutually exclusive with sources and n.

  • n (integer, optional)

    • When set, returns the last N image files from the primary MEDIA_GEN_DIRS[0] directory.

    • Files are sorted by modification time (most recently modified first).

    • Mutually exclusive with sources and ids.

  • compression (object, optional)

    • max_size (integer, optional): Max dimension in pixels. Images larger than this will be resized.

    • max_bytes (integer, optional): Target max file size in bytes. Default: 819200 (800KB).

    • quality (integer, optional): JPEG/WebP quality 1-100. Default: 85.

    • format ("jpeg" | "png" | "webp", optional): Output format. Default: jpeg.

  • response_format ("url" | "path" | "b64_json", default: "url")

    • Response format: file/URL-based (url), local path (path), or inline base64 (b64_json).

  • tool_result ("resource_link" | "image", default: "resource_link")

    • Controls content[] shape:

      • "resource_link" emits ResourceLink items (file/URL-based)

      • "image" emits base64 ImageContent blocks

  • file (string, optional)

    • Base path for output files. If multiple images, index suffix is added.

Behavior notes:

  • Images are processed in parallel for maximum throughput.

  • Compression is only applied when compression options are provided.

  • Compression uses sharp with iterative quality/size reduction when enabled.

  • Partial success: if some sources fail, successful images are still returned with errors listed in the response.

  • When n is provided, it is only honored when the MEDIA_GEN_MCP_ALLOW_FETCH_LAST_N_IMAGES environment variable is set to true. Otherwise, the call fails with a validation error.

  • Sometimes an MCP client (for example, ChargeGPT) may not wait for a response from media-gen-mcp due to a timeout. In creative environments where you need to quickly retrieve the latest openai-images-generate / openai-images-edit outputs, you can use fetch-images with the n argument. When the MEDIA_GEN_MCP_ALLOW_FETCH_LAST_N_IMAGES=true environment variable is set, fetch-images will return the last N files from MEDIA_GEN_DIRS[0] even if the original generation or edit operation timed out on the MCP client side.

fetch-videos

Fetch videos from HTTP(S) URLs or local file paths.

Arguments (input schema):

  • sources (string[], optional)

    • Array of video sources: HTTP(S) URLs or file paths (absolute or relative to the first MEDIA_GEN_DIRS entry).

    • Min: 1, Max: 20 videos.

    • Mutually exclusive with ids and n.

  • ids (string[], optional)

    • Array of video IDs to fetch by local filename match under the primary MEDIA_GEN_DIRS[0] directory.

    • IDs must be safe ([A-Za-z0-9_-] only; no .., *, ?, slashes).

    • Matches filenames containing _{id}_ or _{id}. (supports both single outputs and multi-asset suffixes like _thumbnail.webp).

    • When ids is used, file is not supported (no downloads; returns existing files).

    • Mutually exclusive with sources and n.

  • n (integer, optional)

    • When set, returns the last N video files from the primary MEDIA_GEN_DIRS[0] directory.

    • Files are sorted by modification time (most recently modified first).

    • Mutually exclusive with sources and ids.

  • tool_result ("resource_link" | "resource", default: "resource_link")

    • Controls content[] shape:

      • "resource_link" emits ResourceLink items (file/URL-based)

      • "resource" emits EmbeddedResource blocks with base64 resource.blob

  • file (string, optional)

    • Base path for output files (used when downloading from URLs). If multiple videos are downloaded, an index suffix is added.

Output:

  • content: one resource_link (default) or embedded resource block per resolved video, plus an optional error summary text block.

  • structuredContent: { data: [{ source, uri, file, mimeType, name, downloaded }], errors?: string[] }.

Behavior notes:

  • URL downloads are only allowed when the URL matches MEDIA_GEN_URLS (when set).

  • When n is provided, it is only honored when the MEDIA_GEN_MCP_ALLOW_FETCH_LAST_N_VIDEOS environment variable is set to true. Otherwise, the call fails with a validation error.

fetch-document

Fetch documents from HTTP(S) URLs or local file paths.

Arguments (input schema):

  • sources (string[])

    • Array of document sources: HTTP(S) URLs or file paths (absolute or relative to the first MEDIA_GEN_DIRS entry).

    • Min: 1, Max: 20 documents.

  • tool_result ("resource_link" | "resource", default: "resource_link")

    • Controls content[] shape:

      • "resource_link" emits ResourceLink items (file/URL-based)

      • "resource" emits EmbeddedResource blocks with base64 resource.blob

  • file (string, optional)

    • Base path for output files (used when downloading from URLs). If multiple documents are downloaded, an index suffix is added.

Output:

  • content: one resource_link (default) or embedded resource block per resolved document, plus an optional error summary text block.

  • structuredContent: { data: [{ source, uri, file, mimeType, name, downloaded }], errors?: string[] }.

Behavior notes:

  • URL downloads are only allowed when the URL matches MEDIA_GEN_URLS (when set).

  • Local paths are validated against MEDIA_GEN_DIRS and can be provided as file:// URLs.

  • Default filenames use output_<time_t>_media-gen__fetch-document_<uuid>.<ext> when file is omitted.

test-images

Debug tool for testing MCP result placement without calling OpenAI API.

Enabled only when MEDIA_GEN_MCP_TEST_SAMPLE_DIR is set. The tool reads existing images from this directory and does not create new files.

Arguments (input schema):

  • response_format ("url" | "path" | "b64_json", default: "url")

  • result_placement ("content" | "api" | "structured" | "toplevel" or array of these, optional)

    • Override MEDIA_GEN_MCP_RESULT_PLACEMENT for this call.

  • compression (object, optional)

    • Same logical tuning knobs as fetch-images, but using camelCase keys:

  • tool_result ("resource_link" | "image", default: "resource_link")

    • Controls content[] shape:

      • "resource_link" emits ResourceLink items (file/URL-based)

      • "image" emits base64 ImageContent blocks

      • maxSize (integer, optional): max dimension in pixels.

      • maxBytes (integer, optional): target max file size in bytes.

      • quality (integer, optional): JPEG/WebP quality 1–100.

      • format ("jpeg" | "png" | "webp", optional): output format.

Behavior notes:

  • Reads up to 10 images from the sample directory (no sorting — filesystem order).

  • Uses the same result-building logic as openai-images-generate and openai-images-edit (including result_placement overrides).

  • When output == "base64" and compression is provided, sample files are read and compressed in memory using sharp; original files on disk are never modified.

  • Useful for testing how different MCP clients handle various result structures.

  • When result_placement includes "api", the tool returns a mock OpenAI Images API-style object:

    • Top level: created, data[], background, output_format, size, quality.

    • For response_format: "b64_json" each data[i] contains b64_json.

    • For response_format: "path" each data[i] contains path.

    • For response_format: "url" each data[i] contains url instead of b64_json.

Debug CLI helpers for test-images

For local debugging there are two helper scripts that call test-images directly:

  • npm run test-images – uses debug/debug-call.ts and prints the validated CallToolResult as seen by the MCP SDK client. Usage:

    npm run test-images -- [placement] [--response_format url|path|b64_json]
    # examples:
    # npm run test-images -- structured --response_format b64_json
    # npm run test-images -- structured --response_format path
    # npm run test-images -- structured --response_format url
  • npm run test-images:raw – uses debug/debug-call-raw.ts and prints the raw JSON-RPC result (the underlying CallToolResult without extra wrapping). Same CLI flags as above.

Both scripts truncate large fields for readability:

  • image_url → first 80 characters, then ...(N chars);

  • b64_json and data (when it is a base64 string) → first 25 characters, then ...(N chars).


🧩 Version policy

Semantic Versioning (SemVer)

This package follows SemVer: MAJOR.MINOR.PATCH (x.y.z).

  • MAJOR — breaking changes (tool names, input schemas, output shapes).

  • MINOR — new tools or backward-compatible additions (new optional params, new fields in responses).

  • PATCH — bug fixes and internal refactors with no intentional behavior change.

Since 1.0.0, this project follows standard SemVer rules: breaking changes bump MAJOR (npm’s ^1.0.0 allows 1.x, but not 2.0.0).

Dependency policy

This repository aims to stay closely aligned with current stable releases:

  • MCP SDK: targeting the latest stable @modelcontextprotocol/sdk and schema.

  • OpenAI SDK: regularly updated to the latest stable openai package.

  • Zod: using the Zod 4.x line (currently ^4.1.3). In this project we previously ran on Zod 3.x and, in combination with the MCP TypeScript SDK typings, hit heavy TypeScript errors when passing .shape into inputSchema — in particular TS2589 ("type instantiation is excessively deep and possibly infinite") and TS2322 (schema shape not assignable to AnySchema | ZodRawShapeCompat). We track the upstream discussion in modelcontextprotocol/typescript-sdk#494 and the related Zod typing work in colinhacks/zod#5222, and keep the stack on a combination that passes full strict compilation reliably.

  • Tooling stack (Node.js, TypeScript, etc.): developed and tested against recent LTS / current releases, with a dedicated tsconfig-strict.json that enables all strict TypeScript checks (strict, noUnusedLocals, noUnusedParameters, exactOptionalPropertyTypes, noUncheckedIndexedAccess, noPropertyAccessFromIndexSignature, etc.).

You are welcome to pin or downgrade Node.js, TypeScript, the OpenAI SDK, Zod, or other pieces of the stack if your environment requires it, but please keep in mind:

  • we primarily test and tune against the latest stack;

  • issues that only reproduce on older runtimes / SDK versions may be harder for us to investigate and support;

  • upstream compatibility is validated first of all against the latest MCP spec and OpenAI Images API.

This project is intentionally a bit futuristic: it tries to keep up with new capabilities as they appear in MCP and OpenAI tooling (in particular, robust multimodal/image support over MCP and in ChatGPT’s UI). A detailed real‑world bug report and analysis of MCP image rendering in ChatGPT is listed in the References section as a case study.

If you need a long-term-stable stack, pin exact versions in your own fork and validate them carefully in your environment.


🧩 Typed tool callbacks

All tool handlers use strongly typed callback parameters derived from Zod schemas via z.input<typeof schema>:

// Schema definition
const openaiImagesGenerateBaseSchema = z.object({
  prompt: z.string().max(32000),
  background: z.enum(["transparent", "opaque", "auto"]).optional(),
  // ... more fields
});

// Type alias
type OpenAIImagesGenerateArgs = z.input<typeof openaiImagesGenerateBaseSchema>;

// Strictly typed callback
server.registerTool(
  "openai-images-generate",
  { inputSchema: openaiImagesGenerateBaseSchema.shape, ... },
  async (args: OpenAIImagesGenerateArgs, _extra: unknown) => {
    const validated = openaiImagesGenerateSchema.parse(args);
    // ... handler logic
  },
);

This pattern provides:

  • Static type safety — IDE autocomplete and compile-time checks for all input fields.

  • Runtime validation — Zod .parse() ensures all inputs match the schema before processing.

  • MCP SDK compatibilityinputSchema: schema.shape provides the JSON Schema for tool registration.

All tools (openai-images-*, openai-videos-*, fetch-images, fetch-videos, fetch-document, test-images) follow this pattern.


🧩 Tool annotations

This MCP server exposes the following tools with annotation hints:

Tool

readOnlyHint

destructiveHint

idempotentHint

openWorldHint

openai-images-generate

true

false

false

true

openai-images-edit

true

false

false

true

openai-videos-create

true

false

false

true

openai-videos-remix

true

false

false

true

openai-videos-list

true

false

false

true

openai-videos-retrieve

true

false

false

true

openai-videos-delete

true

false

false

true

openai-videos-retrieve-content

true

false

false

true

fetch-images

true

false

false

false

fetch-videos

true

false

false

false

fetch-document

true

false

false

false

test-images

true

false

false

false

These hints help MCP clients understand that these tools:

  • may invoke external APIs or read external resources (open world),

  • do not modify existing project files or user data; they only create new media files (images/videos/documents) in configured output directories,

  • may produce different outputs on each call, even with the same inputs.

Because readOnlyHint is set to true for most tools, MCP platforms (including chatgpt.com) can treat this server as logically read-only and usually will not show "this tool can modify your files" warnings.


📁 Project structure

media-gen-mcp/
├── src/
│   ├── index.ts              # MCP server entry point
│   └── lib/
│       ├── compression.ts    # Image compression (sharp)
│       ├── env.ts            # Env parsing + allowlists (+ glob support)
│       ├── helpers.ts        # URL/path validation, result building
│       ├── logger.ts         # Structured logging + truncation helpers
│       └── schemas.ts        # Zod schemas for all tools
├── test/
│   ├── compression.test.ts             # 12 tests
│   ├── env.test.ts                     # 19 tests
│   ├── fetch-images.integration.test.ts# 2 tests
│   ├── fetch-videos.integration.test.ts# 2 tests
│   ├── helpers.test.ts                 # 31 tests
│   ├── logger.test.ts                  # 10 tests
│   └── schemas.test.ts                 # 64 tests
├── debug/                    # Local debug helpers (MCP client scripts)
├── plan/                     # Design notes / plans
├── dist/                     # Compiled output
├── tsconfig.json
├── vitest.config.ts
├── package.json
├── CHANGELOG.md
├── README.md
└── AGENTS.md

📝 License

MIT


🩺 Troubleshooting

  • Make sure your OPENAI_API_KEY is valid and has image API access.

  • You must have a verified OpenAI organization. After verifying, it can take 15–20 minutes for image API access to activate.

  • File paths [optional param] must be absolute.

    • Unix/macOS/Linux: Starting with / (e.g., /path/to/image.png)

    • Windows: Drive letter followed by : (e.g., C:/path/to/image.png or C:\path\to\image.png)

  • For file output, ensure the target directory is writable.

  • If you see errors about file types, check your image file extensions and formats.


🙏 Inspiration

This server was originally inspired by SureScaleAI/openai-gpt-image-mcp, but is now a separate implementation focused on closely tracking the official specifications:

  • OpenAI Images API alignment – The arguments for openai-images-generate and openai-images-edit mirror images.create / gpt-image-1.5: prompt, n, size, quality, background, output_format, output_compression, user, plus response_format (url / b64_json) with the same semantics as the OpenAI Images API.

  • MCP Tool Result alignment (image + resource_link) – With result_placement = "content", the server follows the MCP 5.2 Tool Result section (5.2.2 Image Content, 5.2.4 Resource Links) and emits strongly-typed content[] items:

    • { "type": "image", "data": "<base64>", "mimeType": "image/png" } for response_format = "b64_json";

    • { "type": "resource_link", "uri": "file:///..." | "https://...", "name": "...", "mimeType": "image/..." } for file/URL-based output.

  • Raw OpenAI-style API output – With result_placement = "api", the tool result itself is an OpenAI Images-style object: { created, data: [...], background, output_format, size, quality, usage? }, where each data[] entry contains either b64_json (for response_format = "b64_json") or url (for response_format = "url"). No MCP wrapper fields (content, structuredContent, files, urls) are added in this mode.

In short, this library:

  • tracks the OpenAI Images API for arguments and result shape when result_placement = "api" with response_format = "url" | "b64_json", and

  • follows the MCP specification for tool result content blocks (image, resource_link, text) when result_placement = "content".

  • Default mode / Claude Desktop / strict MCP clients
    For clients that strictly follow the MCP spec, the recommended (and natural) configuration is:

    • result_placement = content

    • response_format = b64_json

    In this mode the server returns:

    • content[] with type: "image" (base64 image data) and type: "resource_link" (file/URL links), matching MCP section 5.2 (Image Content and Resource Links). This output works well for direct integration with Claude Desktop and any client that fully implements the 2025‑11‑25 spec.

  • chatgpt.com Developer Mode
    For running this server as an MCP backend behind ChatGPT Developer Mode, the most practical configuration is the one that most closely matches the OpenAI Images API:

    • result_placement = api

    • response_format = url

    In this mode the tool result matches the images.create / gpt-image-1.5 format (including data[].url), which simplifies consumption from backends and libraries that expect the OpenAI schema.

    However, even with this OpenAI-native shape, the chatgpt.com client does not currently render images. This behavior is documented in detail in the following report:
    https://github.com/strato-space/report/issues/1


⚠️ Limitations & Large File Handling

  • Configurable payload safeguard: By default this server uses a ~50MB budget (52,428,800 bytes) for inline content to stay within typical MCP client limits. You can override this threshold by setting the MCP_MAX_CONTENT_BYTES environment variable to a higher (or lower) value.

  • Auto-Switch to File Output: If the total image base64 size exceeds the configured threshold, the tool automatically saves images to disk and returns file path(s) via resource_link instead of inline base64. This helps avoid client-side "payload too large" errors while still delivering full-resolution images.

  • Default File Location: If you do not specify a file path, outputs are saved under MEDIA_GEN_DIRS[0] (default: /tmp/media-gen-mcp) using names like output_<time_t>_media-gen__<tool>_<id>.<ext>.

  • Environment Variables:

    • MEDIA_GEN_DIRS: Set this to control where outputs are saved. Example: export MEDIA_GEN_DIRS=/your/desired/dir. This directory may coincide with your public static directory if you serve files directly from it.

    • MEDIA_GEN_MCP_URL_PREFIXES: Optional comma-separated HTTPS prefixes for public URLs, matched positionally to MEDIA_GEN_DIRS entries. When set, the server builds public URLs as <prefix>/<relative_path_inside_root> and returns them alongside file paths (for example via resource_link URIs and structuredContent.data[].url when response_format: "url"). Example: export MEDIA_GEN_MCP_URL_PREFIXES=https://media-gen.example.com/media,https://media-gen.example.com/samples

    • Best Practice: For large or production images, always use file output and ensure your client is configured to handle file paths. Configure MEDIA_GEN_DIRS and (optionally) MEDIA_GEN_MCP_URL_PREFIXES to serve images via a public web server (e.g., nginx).


🌐 Serving generated files over HTTPS

If you want ChatGPT (or any MCP client) to mention publicly accessible URLs alongside file paths:

  1. Expose your image directory via HTTPS. For example, on nginx:

    server {
        # listen 443 ssl http2;
        # server_name <server_name>;
    
        # ssl_certificate     <path>;
        # ssl_certificate_key <path>;
    
        location /media/ {
            alias /home/username/media-gen-mcp/media/;
            autoindex off;
            expires 7d;
            add_header Cache-Control "public, immutable";
        }
    }
  2. Ensure the first entry in MEDIA_GEN_DIRS points to the same directory (e.g. MEDIA_GEN_DIRS=/home/username/media-gen-mcp/media/ or MEDIA_GEN_DIRS=media/ when running from the project root).

  3. Set MEDIA_GEN_MCP_URL_PREFIXES=https://media-gen.example.com/media so the server returns matching HTTPS URLs in top-level urls, resource_link URIs, and image_url fields (for response_format: "url").

Both openai-images-generate and openai-images-edit now attach files + urls for base64 and file response modes, allowing clients to reference either the local filesystem path or the public HTTPS link. This is particularly useful while ChatGPT cannot yet render MCP image blocks inline.


📚 References


🙏 Credits

Available Tools

14 tools
fetch-documentFetch DocumentB
Read-only

Fetch documents from URLs or local file paths. Downloads remote URLs into MEDIA_GEN_DIRS and returns MCP content blocks as resource_link (default) or embedded resource.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourcesYesArray of document sources: HTTP(S) URLs or file paths (absolute or relative to the first MEDIA_GEN_DIRS entry). Max 20 documents.
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'resource' emits EmbeddedResource blocks with base64 blob.resource_link
fileNoBase path for output files (used when downloading from URLs). If multiple documents are downloaded, an index suffix is added.

TDQS

B3.2/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states 'Downloads remote URLs into MEDIA_GEN_DIRS', indicating a write operation, but annotations set readOnlyHint=true. This contradiction severely undermines transparency and could mislead an agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences: the first states the core purpose, the second adds key details. No fluff, front-loaded, and every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the main behavior, output types, and download destination. However, missing details like supported document formats, error handling, and a description of MEDIA_GEN_DIRS, along with the contradiction, prevent full completeness. Still adequate for a simple tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already describes all parameters. The description adds context about output formats (resource_link vs embedded resource) but does not explain the 'file' parameter further. It meets the baseline but adds limited value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it fetches documents from URLs or local file paths, differentiating it from sibling tools like fetch-images and fetch-videos. However, it does not explicitly name these alternatives, slightly reducing clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or when-not-to-use guidance is provided. The purpose is implied by the tool name and sibling context, but an agent might not know if this tool supports all document types or if there are prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fetch-imagesFetch ImagesA
Read-only

Fetch and process images from URLs or local file paths. Returns MCP CallToolResult with content[] (ResourceLink or ImageContent based on tool_result param) and structuredContent (OpenAI ImagesResponse format with data[].url, data[].path, or data[].b64_json based on response_format param).

ParametersJSON Schema
NameRequiredDescriptionDefault
sourcesNoArray of image sources: HTTP(S) URLs or file paths (absolute or relative to the first MEDIA_GEN_DIRS entry). Max 20 images. Mutually exclusive with 'n'.
idsNoArray of image IDs to fetch by filename match (looks for filenames containing _{id}_ or _{id}. under the primary MEDIA_GEN_DIRS[0] directory). Mutually exclusive with 'sources' and 'n'.
nNoWhen set, returns the last N image files from the primary MEDIA_GEN_DIRS[0] directory (most recently modified first). Mutually exclusive with 'sources'.
compressionNoCompression options. If omitted, no compression is applied.
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'image' emits base64 ImageContent blocks.resource_link
response_formatNoControls structuredContent shape: 'url' (default) emits data[].url, 'path' emits data[].path, 'b64_json' emits data[].b64_json.url
fileNoBase path for output files, absolute or relative to the first MEDIA_GEN_DIRS entry. If multiple images, index suffix is added.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive behavior. The description adds value by detailing processing and output format options, enhancing transparency beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose, and no wasted words. Efficiently conveys the core functionality and output structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich schema and annotations, the description is adequate. It covers the return type and high-level behavior, though some processing details are only in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with detailed descriptions for each parameter. The tool description does not add significant meaning beyond the schema, meeting the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it fetches and processes images from URLs or file paths, distinguishing it from sibling tools like fetch-document and fetch-videos. It specifies the output format in detail.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for fetching images but does not provide explicit guidance on when to use this tool versus alternatives like fetch-document or image generation tools. No 'when-not' or context provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fetch-videosFetch VideosB
Read-only

Fetch videos from URLs or local file paths. Returns MCP CallToolResult with content blocks (tool_result=resource_link|resource) and structuredContent listing resolved files/URLs.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourcesNoArray of video sources: HTTP(S) URLs or file paths (absolute or relative to the first MEDIA_GEN_DIRS entry). Max 20 videos. Mutually exclusive with 'n'.
idsNoArray of video IDs to fetch by filename match (looks for filenames containing _{id}_ or _{id}. under the primary MEDIA_GEN_DIRS[0] directory). Mutually exclusive with 'sources' and 'n'.
nNoWhen set, returns the last N video files from the primary MEDIA_GEN_DIRS[0] directory (most recently modified first). Mutually exclusive with 'sources'.
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'resource' emits EmbeddedResource blocks with base64 blob.resource_link
fileNoBase path for output files (when downloading from URLs), absolute or relative to the first MEDIA_GEN_DIRS entry. If multiple videos are downloaded, an index suffix is added.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only behavior. Description adds return format details (content blocks, structuredContent) but omits that URL fetching downloads files (implied by 'file' parameter). Does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two front-loaded sentences with zero wasted words. Purpose and return format are conveyed efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description explains return format but lacks detail on 'structuredContent'. Mutual exclusivity of inputs is covered in schema, but the description could supplement this for clarity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so parameters are well documented. Description adds value by explaining the tool_result parameter's impact and return structure, providing context beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states 'Fetch videos' and distinguishes from sibling fetch tools by specifying videos. However, it does not fully capture the multiple selection methods (sources, ids, n), making it slightly incomplete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus siblings like fetch-document or fetch-images, nor on choosing among the three input methods. The description focuses on return format instead of usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

google-videos-generateGoogle Videos GenerateB
Read-only

Generate videos using Google GenAI (Veo). Can optionally wait for completion and download generated videos to MEDIA_GEN_DIRS.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptNoText prompt that describes the video to generate (max 32K chars). Required unless an input image/video is provided.
input_referenceNoOptional image reference (image-to-video): HTTP(S) URL, base64 / data URL, or file path under MEDIA_GEN_DIRS.
input_reference_mime_typeNoOptional override for input image MIME type (e.g. image/jpeg). Useful when input_reference is raw base64 without a data URL header.
input_video_referenceNoOptional input video reference (video extension): HTTP(S) URL or file path under MEDIA_GEN_DIRS. Mutually exclusive with input_reference.
modelNoGoogle video model id (default: veo-3.1-generate-001).veo-3.1-generate-001
number_of_videosNoNumber of videos to generate (default: 1).
aspect_ratioNoAspect ratio for the generated video.
duration_secondsNoVideo duration in seconds (provider/model-dependent).
person_generationNoControls whether people are allowed in the generated video.
wait_for_completionNoIf true, poll the operation until done (then optionally download). Default: true.
timeout_msNoMax time to wait for completion when wait_for_completion is true (default: 900000).
poll_interval_msNoPolling interval when wait_for_completion is true (default: 10000).
download_when_doneNoWhen waiting, whether to download generated videos to MEDIA_GEN_DIRS[0]. Defaults to true when wait_for_completion=true, otherwise false.
tool_resultNoControls content[] shape when downloading: 'resource_link' (default) emits ResourceLink items, 'resource' emits EmbeddedResource blocks with base64 blob.resource_link
response_formatNoControls structuredContent video fields: 'url' (default) prefers video.uri, 'b64_json' prefers video.videoBytes.url

TDQS

B3.1/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description claims to generate videos (a write operation), but the annotation says readOnlyHint=true. This is a direct contradiction. Additionally, no information about destruction, authentication, or rate limits is provided.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very concise (two sentences) and front-loaded with purpose. However, it lacks structure (e.g., sections) but is efficient for a simple tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 15 parameters and no output schema, the description is too brief. It does not explain common use cases (e.g., image-to-video, video extension), return value shape, or when to use different parameter combinations. The schema covers details, but description should summarize.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with detailed parameter descriptions. The description adds no parameter-level information beyond 'Can optionally wait for completion and download...' which is already implied by parameters. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it generates videos using Google GenAI (Veo) and mentions optional waiting and downloading. This distinguishes it from sibling tools like OpenAI video generation and retrieval tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use (generate a video) but does not provide explicit guidance on when not to use or alternatives. It mentions optional waiting and downloading, but no context on trade-offs or prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

google-videos-retrieve-contentGoogle Videos Retrieve ContentA
Read-only

Download generated video content for a completed Google video operation, write it under MEDIA_GEN_DIRS, and return content blocks (tool_result=resource_link|resource).

ParametersJSON Schema
NameRequiredDescriptionDefault
operation_nameYesGoogle video operation name/id.
indexNoWhich generatedVideos[index] to download (default: 0).
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'resource' emits EmbeddedResource blocks with base64 blob.resource_link
response_formatNoControls structuredContent video fields: 'url' (default) prefers video.uri, 'b64_json' prefers video.videoBytes.url

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses the side effect of writing to MEDIA_GEN_DIRS, which goes beyond the readOnlyHint and destructiveHint annotations. The description adds useful behavioral context not captured in annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence is adequate but packs multiple actions (download, write, return) into one clause, reducing clarity. Could be more straightforward.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Lacks output schema and does not describe the exact return value format beyond referencing content blocks. Given the complexity, a short description of the returned structure would be beneficial.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% description coverage, already explaining all parameters. The description mentions tool_result=resource_link|resource, but this adds no new meaning beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it downloads generated video content for completed Google video operations, distinguishing it from generation and retrieval of operation status. However, it does not explicitly differentiate from similar sibling tools like openai-videos-retrieve-content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies usage after a completed generation operation but provides no explicit guidance on when to use this tool versus alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

google-videos-retrieve-operationGoogle Videos Retrieve OperationA
Read-only

Retrieve the status/result of a Google video generation operation (response_format=url|b64_json controls uri vs videoBytes in structuredContent).

ParametersJSON Schema
NameRequiredDescriptionDefault
operation_nameYesGoogle video operation name/id.
response_formatNoControls structuredContent video fields: 'url' (default) prefers video.uri, 'b64_json' prefers video.videoBytes.url

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds context beyond annotations by explaining that it retrieves status/result and that the response_format parameter controls whether the output uses uri or videoBytes. This is consistent with the readOnlyHint=true annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that efficiently conveys purpose and parameter influence, with no extraneous information. It is front-loaded with the core action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with two well-documented parameters. The description covers purpose and a key parameter effect. However, it lacks details on return format for operations still in progress or error conditions, though these are partially implied.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, so baseline is 3. The description paraphrases the parameter effect but does not add significant meaning beyond the schema's own description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it retrieves the status/result of a Google video generation operation, specifying the verb and resource. It differentiates from sibling tools like 'google-videos-retrieve-content' by focusing on status/result rather than content retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not provide explicit guidance on when to use this tool versus alternatives such as 'google-videos-retrieve-content' or other video retrieval tools. Usage context is implied but not stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-images-editOpenAI Images EditA
Read-only

Edit images (inpainting, outpainting, compositing) from 1 to 16 inputs using OpenAI gpt-image-1.5 (default) or gpt-image-1. Returns MCP CallToolResult with content[] (ResourceLink or ImageContent based on tool_result param) and structuredContent (OpenAI ImagesResponse format with data[].url, data[].path, or data[].b64_json based on response_format param).

ParametersJSON Schema
NameRequiredDescriptionDefault
imageYesAbsolute image path, base64 string, or HTTP(S) URL to edit, or an array of such values (1-16 images).
promptYesA text description of the desired edit. Max 32000 chars.
maskNoOptional absolute path, base64 string, or HTTP(S) URL for a mask image (png < 4MB, same dimensions as the first image). Fully transparent areas indicate where to edit.
modelNogpt-image-1.5
nNoNumber of images to generate (1-10).
qualityNoQuality (high, medium, low). Default: high.high
sizeNoSize of the generated images. Default: 1024x1536.1024x1536
userNoOptional user identifier for OpenAI monitoring.
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'image' emits base64 ImageContent blocks.resource_link
response_formatNoControls structuredContent shape: 'url' (default) emits data[].url, 'path' emits data[].path, 'b64_json' emits data[].b64_json.url

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description details the output format (CallToolResult with content[] and structuredContent) and the role of tool_result and response_format params, adding value beyond annotations which already indicate read-only behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence but packs essential info efficiently; however, it could be better structured for readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich schema and no output schema, the description adequately explains the output structure and main purpose, though it omits details like mask constraints.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 90% schema description coverage, the description adds only marginal value (e.g., listing edit types and model names). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Edit images (inpainting, outpainting, compositing)' with specific models and input counts, distinguishing it from the sibling 'openai-images-generate' tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

While not explicitly stating when not to use, the description implies usage for image editing tasks and the sibling list shows relevant alternatives, providing clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-images-generateOpenAI Images GenerateC
Read-only

Generate images from text prompts using OpenAI gpt-image-1.5 (default) or gpt-image-1. Returns MCP CallToolResult with content[] (ResourceLink or ImageContent based on tool_result param) and structuredContent (OpenAI ImagesResponse format with data[].url, data[].path, or data[].b64_json based on response_format param).

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYes
backgroundNo
modelNogpt-image-1.5
moderationNo
nNo
output_compressionNo
output_formatNo
qualityNohigh
sizeNo1024x1536
userNo
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'image' emits base64 ImageContent blocks.resource_link
response_formatNoControls structuredContent shape: 'url' (default) emits data[].url, 'path' emits data[].path, 'b64_json' emits data[].b64_json.url

TDQS

C2.4/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states 'Generate images' which is a creation action, but annotations set readOnlyHint=true, creating a contradiction. Adding behavioral context like API credit consumption or rate limits would be needed, but is absent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences and front-loads the action. It is concise but could be better structured to separate purpose from return details. Still efficient overall.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 12 parameters, no output schema, and low schema coverage, the description does not provide sufficient context for an agent to select and invoke the tool correctly. Missing parameter explanations and usage context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With only 17% schema coverage, the description fails to explain most parameters (prompt, model, size, etc.). It only indirectly mentions tool_result and response_format in the return description, but does not define their values or behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it generates images from text prompts using specific models, and mentions default model. This distinguishes it from siblings like openai-images-edit, though not explicitly, which prevents a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like openai-images-edit or fetch-images. It does not specify prerequisites, contexts, or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-videos-createOpenAI Videos CreateB
Read-only

Create a video generation job using the OpenAI Videos API. Returns structuredContent with the OpenAI Video job object, and (optionally) downloaded assets as MCP content blocks (tool_result=resource_link|resource).

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesText prompt that describes the video to generate (max 32K chars).
input_referenceNoOptional image reference: HTTP(S) URL, base64 / data URL, or file path.
input_reference_fitNoHow to fit input_reference to the requested video size: match (require exact), cover (crop), contain (pad), stretch (distort). Default: contain.contain
input_reference_backgroundNoPadding background when input_reference_fit=contain: blur (default), black, white, or hex color (#RRGGBB/#RRGGBBAA).blur
modelNoVideo model to use (default: sora-2-pro).sora-2-pro
secondsNoClip duration in seconds (default: 4 seconds).
sizeNoOutput resolution formatted as width x height. Sizes 1024x1792 and 1792x1024 require sora-2-pro.
wait_for_completionNoIf true, poll the job until completed/failed (then optionally download assets). Default: true.
timeout_msNoMax time to wait for completion when wait_for_completion is true (default: 900000).
poll_interval_msNoPolling interval when wait_for_completion is true (default: 2000).
download_variantsNoWhich downloadable assets to fetch when completed (default: ['video']).
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'resource' emits EmbeddedResource blocks with base64 blob.resource_link

TDQS

B3.1/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description claims the tool creates a video job, which is a write operation, but the annotations declare readOnlyHint=true, indicating a read-only operation. This is a direct contradiction, making the description misleading. Additionally, the description does not disclose behavioral traits like job lifecycle or side effects beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long and covers the core action and output. It is efficient and front-loaded with the primary purpose, though it could be improved by structuring the output behavior more explicitly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (12 parameters, no output schema), the description lacks essential context about job lifecycle, polling behavior, and exact return format. It mentions optional downloads but does not explain how the agent should handle job status or errors, leaving significant gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters. The description adds no additional parameter-level information beyond what the schema provides, meeting the baseline for this dimension.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's action ('create a video generation job'), specifies the API (OpenAI Videos API), and describes the return value (structuredContent with job object and optional assets). This distinguishes it from sibling tools like openai-videos-retrieve or openai-videos-delete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for creating new video generation jobs, but lacks explicit guidance on when to use this tool versus alternatives like openai-videos-remix or google-videos-generate. No when-not-to-use conditions or prerequisites are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-videos-deleteOpenAI Videos DeleteC
Read-only

Delete a video job by id using the OpenAI Videos API.

ParametersJSON Schema
NameRequiredDescriptionDefault
video_idYesVideo job id to delete.

TDQS

C2.8/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotation contradiction: description says 'Delete' (destructive) but annotations claim readOnlyHint=true. No further behavioral context added; expected destructive behavior is contradicted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Very concise single sentence, but lacks necessary detail. Front-loading is acceptable, but brevity sacrifices informativeness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 1-param tool with no output schema and contradictory annotations, description fails to explain consequences of deletion, reversibility, or success confirmation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so baseline 3. Description does not add meaning beyond the schema; merely restates parameter role.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states verb 'Delete', resource 'video job by id', and API. It distinguishes from sibling tools like create, list, retrieve, remix.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool vs alternatives, no prerequisites or conditions. Among many sibling tools, agent has no basis for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-videos-listOpenAI Videos ListB
Read-only

List video jobs using the OpenAI Videos API. Returns structuredContent with the OpenAI list response shape { data, has_more, last_id }.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoCursor (video id) to list after.
limitNoPage size.
orderNoSort order of results by timestamp.

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true and destructiveHint=false, so the agent knows it's a safe read. The description adds return format info but no further behavioral traits beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with the main action. Every sentence adds value, though could be slightly more structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with well-documented parameters and no output schema, the description sufficiently explains the return shape. Adequate given the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All parameters are documented in the schema with descriptions. The description adds no additional parameter information beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'List video jobs' which is a specific verb and resource. It distinguishes from sibling tools like openai-videos-retrieve (single video) but does not explicitly name alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives. Sibling tools exist for single retrieval and creation, but the description lacks usage context or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-videos-remixOpenAI Videos RemixB
Read-only

Create a remix video job from an existing video_id. Returns structuredContent with the OpenAI Video job object, and (optionally) downloaded assets as MCP content blocks (tool_result=resource_link|resource).

ParametersJSON Schema
NameRequiredDescriptionDefault
video_idYesSource video job id to remix.
promptYesUpdated prompt that directs the remix (max 32K chars).
wait_for_completionNoIf true, poll the job until completed/failed (then optionally download assets). Default: true.
timeout_msNoMax time to wait for completion when wait_for_completion is true (default: 900000).
poll_interval_msNoPolling interval when wait_for_completion is true (default: 2000).
download_variantsNoWhich downloadable assets to fetch when completed (default: ['video']).
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'resource' emits EmbeddedResource blocks with base64 blob.resource_link

TDQS

B3.4/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description claims to 'Create a remix video job', which is a write/mutation operation, contradicting the annotation readOnlyHint=true. This is a serious inconsistency (annotation_contradiction=true). The description also doesn't disclose potential side effects beyond creation, such as cost implications or state changes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences efficiently convey purpose and return format. The first sentence immediately states the core action, and the second explains the output. No extraneous information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the essential aspects: what the tool does, the source video, and the return structure. However, it omits details about the job object shape (no output schema), and the 'structuredContent' term is not explained. Despite this, it provides sufficient context for typical usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All 7 parameters have descriptions in the input schema (coverage 100%), so the description adds minimal additional meaning. It references return format but does not elaborate on parameter specifics; baseline 3 is appropriate as schema already carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Create a remix video job'), the resource ('from an existing video_id'), and the result (returns job object and optionally assets). It effectively distinguishes from sibling tools like openai-videos-create or openai-videos-retrieve by specifying the remix operation on an existing video.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description identifies the tool's purpose but does not provide explicit guidance on when to choose it over alternatives (e.g., openai-videos-create for new videos) or when not to use it. No prerequisites or conditions are stated, leaving the agent to infer from context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-videos-retrieveOpenAI Videos RetrieveA
Read-only

Retrieve a video job by id using the OpenAI Videos API.

ParametersJSON Schema
NameRequiredDescriptionDefault
video_idYesVideo job id.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description says 'Retrieve' which aligns with the readOnlyHint annotation. However, it does not add any behavioral details beyond annotations, such as what happens if the job ID is invalid or whether the operation is idempotent (annotation says false but not explained). Adequate but not enhanced.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, 10 words, front-loaded with the key action and resource. No extraneous information. Efficient and to the point.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple retrieval tool, the description is minimally complete. It states what it does, but lacks details about response format, error handling, or differentiation from content retrieval. Given the absence of output schema, some additional context would be beneficial.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% coverage with a single parameter 'video_id' described as 'Video job id.' The description adds no further meaning beyond the schema. Baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Retrieve a video job by id' which is a specific verb-resource pair. It distinguishes from siblings like 'openai-videos-list' (list all) and 'openai-videos-retrieve-content' (get content) by focusing on the job itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No usage guidelines provided. The description does not specify when to use this tool over alternatives, such as when to retrieve vs. list, or what prerequisites (e.g., a valid job ID) are needed. An explicit note about using this tool when having an ID would help.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openai-videos-retrieve-contentOpenAI Videos Retrieve ContentA
Read-only

Retrieve a video asset (video/thumbnail/spritesheet) for a completed job, write it under MEDIA_GEN_DIRS, and return content blocks (tool_result=resource_link|resource).

ParametersJSON Schema
NameRequiredDescriptionDefault
video_idYesVideo job id.
variantNoWhich downloadable asset to return (default: video).video
tool_resultNoControls content[] shape: 'resource_link' (default) emits ResourceLink items, 'resource' emits EmbeddedResource blocks with base64 blob.resource_link

TDQS

A3.7/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description claims the tool writes a file under MEDIA_GEN_DIRS, which is a write operation, but annotations declare readOnlyHint=true. This is a contradiction. No other behavioral traits are disclosed beyond the contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence of about 25 words, front-loaded with the purpose. No redundant or wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the main purpose and parameter details, but lacks specifics on output structure (e.g., shape of resource_link vs resource) and file path conventions. With no output schema, this leaves gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, baseline 3. The description adds meaning: 'video asset' maps to variant enum, explains tool_result param, and adds 'completed job' context for video_id, going beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'retrieve' and resource 'video asset', clarifying the exact type (video/thumbnail/spritesheet). It distinguishes from siblings like 'google-videos-retrieve-content' by being OpenAI-specific, and adds details about writing to MEDIA_GEN_DIRS and returning content blocks.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states 'for a completed job', providing context on when to use. However, it does not explicitly contrast with siblings like 'openai-videos-retrieve' or 'openai-videos-list', leaving some ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

B3.4/5.0
Disambiguation5/5

Tools are clearly grouped by provider and media type (fetch, google-videos, openai-images, openai-videos). Each tool serves a distinct purpose: fetching existing content, generating/editing images, or creating/managing videos. No significant overlap in functionality.

Naming Consistency4/5

Most tools follow a consistent {provider}-{mediaType}-{action} pattern (e.g., openai-images-generate, google-videos-retrieve-operation). The generic fetch tools (fetch-document, fetch-images, fetch-videos) break the pattern slightly but are still clear and predictable.

Tool Count5/5

14 tools is well-scoped for a media generation server. It covers fetching, image generation/editing, and video creation/management without being overwhelming. Each tool has a clear role.

Completeness4/5

The tool surface covers core media operations: fetch, generate, edit images, and create/retrieve/delete videos from OpenAI. Minor gaps include lack of Google video job listing/deletion and no image generation from other providers, but the domain is competently covered.

Maintenance

ActivityInactive
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/strato-space/media-gen-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server