Skip to main content
Glama

claude-media-mcp

An MCP server that lets any MCP-capable chat or agent (Claude Code, Claude Desktop, Codex, VS Code, Antigravity, Cursor, claude.ai connectors and others) generate images, video and audio through OpenAI, Google Gemini, fal.ai and Cloudflare Workers AI. You can also send every request through your Cloudflare AI Gateway.

One Python file, three dependencies, one .env for all your clients.

Image

Video

Audio

OpenAI

gpt-image-2 (generate + edit)

sora-2

gpt-4o-mini-tts

Gemini

gemini-3-pro-image (Nano Banana Pro, generate + edit)

veo-3.1-generate-preview

gemini-3.8-flash-tts (WAV)

fal.ai

fal-ai/nano-banana-pro, or any fal model

fal-ai/veo3.1/fast, or any

fal-ai/elevenlabs/tts/turbo-v2.5, or any

Cloudflare Workers AI

@cf/black-forest-labs/flux-1-schnell

-

@cf/deepgram/aura-1

Every tool also takes a model override, so any model the provider offers works.

Quick start

Requires uv and Python 3.11+.

git clone https://github.com/righttechsoft/claude-media-mcp.git
cd claude-media-mcp
uv sync
cp .env.example .env    # then fill in the keys you have

Only providers whose key is set are used. .env sits next to server.py and is read on every start; real environment variables take precedence.

Related MCP server: media-gen-mcp

Connect a client

The server speaks MCP over stdio. Every client launches the same command:

uv run --directory /path/to/claude-media-mcp server.py

Or, to skip uv at launch time, the project's virtualenv Python directly: /path/to/claude-media-mcp/.venv/bin/python /path/to/claude-media-mcp/server.py (on Windows: .venv\Scripts\python.exe).

Claude Code (all projects):

claude mcp add -s user media -- uv run --directory /path/to/claude-media-mcp server.py

Claude Desktop (claude_desktop_config.json), Antigravity (~/.gemini/antigravity/mcp_config.json), Cursor (~/.cursor/mcp.json):

{
  "mcpServers": {
    "media": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/claude-media-mcp", "server.py"]
    }
  }
}

Codex (~/.codex/config.toml):

[mcp_servers.media]
command = "uv"
args = ["run", "--directory", "/path/to/claude-media-mcp", "server.py"]

VS Code (user mcp.json):

{
  "servers": {
    "media": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--directory", "/path/to/claude-media-mcp", "server.py"]
    }
  }
}

GUI apps sometimes don't see your shell PATH. If a client can't find uv, use its absolute path or the virtualenv Python shown above.

Tools

All tools take optional provider (default: the first configured one in the order listed), model and options. options is merged into the provider's request, so you can pass any model-specific parameter (quality, seed, resolution, negative prompt and so on).

Files are saved to MEDIA_OUTPUT_DIR (default ~/claude-media) as YYYYmmdd-HHMMSS-provider-id.ext. Each result has the absolute path. In HTTP mode it also has a download link.

generate_image(prompt, provider, model, aspect_ratio, input_images, options)

Order: openai, gemini, fal, cloudflare. Returns the full-size file plus a JPEG preview (max 1024px) the chat can see inline.

  • aspect_ratio like 16:9. OpenAI maps it to the closest supported size.

  • input_images: local paths, URLs or data URIs, used for editing or as references. Not supported on Cloudflare.

start_video(prompt, provider, model, aspect_ratio, duration_seconds, input_image, options) and check_video(job_id, wait_seconds=45)

Order: openai, gemini, fal. Video takes minutes, longer than most clients wait for one tool call, so it is split in two:

  1. start_video submits the job and returns a job_id immediately.

  2. check_video waits up to wait_seconds (max 300). If the video is done it saves it and returns the path. If not, it returns the current status, and the chat calls it again.

The job_id contains the provider's own job reference, so a job started in one session can be collected in another. On fal, duration is model-specific: pass it via options, for example {"duration": "8s"}.

generate_audio(text, provider, model, voice, options)

Order: openai, gemini, fal, cloudflare. Text-to-speech by default. Prompt-based fal models (music, sound effects) take options={"prompt": "..."}.

Configuration

Variable

Purpose

OPENAI_API_KEY

OpenAI

GEMINI_API_KEY (or GOOGLE_API_KEY)

Gemini

FAL_KEY

fal.ai

CF_ACCOUNT_ID + CF_API_TOKEN

Cloudflare Workers AI

CF_AIG_GATEWAY

Cloudflare AI Gateway id. With CF_ACCOUNT_ID, routes all providers through gateway.ai.cloudflare.com

CF_AIG_TOKEN

Optional, for authenticated gateways (cf-aig-authorization header)

MEDIA_OUTPUT_DIR

Output folder, default ~/claude-media

MCP_HOST, MCP_PORT

HTTP mode bind address, default 127.0.0.1:47213

MCP_TOKEN

HTTP mode secret: the endpoint becomes /{MCP_TOKEN}/mcp. Required when binding to a non-loopback host

MCP_PUBLIC_URL

Public base URL used in file download links, for example behind a tunnel

With the AI Gateway enabled, each provider still needs its own key. Gateway-stored keys (BYOK) without a local key are not supported yet.

HTTP mode (remote clients)

uv run server.py --http

Serves streamable HTTP at http://127.0.0.1:47213/mcp and generated files at /files/<name>. To reach it from claude.ai or another machine, set MCP_TOKEN and MCP_PUBLIC_URL, put it behind a tunnel (for example Cloudflare Tunnel), and add https://your-host/{MCP_TOKEN}/mcp as a custom connector.

The server spends your API credits, so it refuses to bind to a non-loopback address without MCP_TOKEN. Treat the token like a password.

Development

uv run python test_server.py

Offline checks only: no API calls, no keys needed.

mcp is pinned below 2.0 because the mcp.server.fastmcp API this server uses was removed in the 2.x SDK.

License

MIT

Available Tools

4 tools
check_videoA

Wait for a video job started by start_video. Polls for up to wait_seconds (0-300, default 45). When the video is ready, saves it to disk and returns its path. If it is still running, returns a status message with the job_id; call check_video again with the same job_id until the path is returned. Failures raise an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYes
wait_secondsNo

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it discloses blocking/wait behavior (poll up to 0-300s), a real side effect (saves the video to disk and returns its path), the non-terminal return shape (status message plus job_id), and error behavior ('failures raise an error'). It omits file naming/location and any auth or rate-limit context, so it is strong but not exhaustive.

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?

Four tight sentences, front-loaded with purpose and timing, then the success path, then the retry path, then failures. Every sentence adds an actionable fact with no filler.

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?

There is no output schema and no annotations, so the description correctly explains the return values (file path vs. status message with job_id) and the error case. It is nearly complete for a two-parameter polling tool; only the saved file's destination/naming convention is left unstated.

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 description coverage is 0%, so the description must compensate, and it does for the key parameter by giving wait_seconds' range and default (0-300, default 45) beyond the schema's bare default. job_id's meaning and its reuse across polls are implied rather than defined, which is the only real gap.

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?

States a specific verb and resource ('Wait for a video job started by start_video') and names the sibling that must precede it, so an agent can immediately place it in the video pipeline rather than confusing it with generate_image or generate_audio.

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?

Gives a clear precondition (only after start_video) and an explicit repeated-call loop ('call check_video again with the same job_id until the path is returned'). It does not need to name alternatives since none of the other siblings poll a job, but it stops short of stating any when-not condition or termination limit on retries.

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

generate_audioA

Text-to-speech (and prompt-based audio on fal). Saves the audio file to disk and returns its path.

provider (default: first configured of openai, gemini, fal, cloudflare):

  • openai: default gpt-4o-mini-tts, voice default alloy, mp3 output. options merged into the request (e.g. instructions, speed, response_format).

  • gemini: default gemini-3.8-flash-tts, voice default Kore (prebuilt voice name). options shallow-update generationConfig. Output is WAV.

  • fal: default fal-ai/elevenlabs/tts/turbo-v2.5. Input {text, voice} updated with options. Prompt-based fal audio models (music, sound effects) take options={"prompt": "..."}; any model id works.

  • cloudflare: default @cf/deepgram/aura-1. Body {text, speaker=voice} updated with options.

ParametersJSON Schema
NameRequiredDescriptionDefault
textYes
modelNo
voiceNo
optionsNo
providerNo

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does disclose the critical trait an agent needs: this writes an audio file to disk and returns its path rather than returning bytes. It also documents per-provider output formats (mp3, WAV) and how each backend's payload is mutated. It stops short of auth/error/rate-limit behavior.

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?

Purpose and side effect are front-loaded in one sentence, followed by a tight provider-by-provider list where every line adds actionable detail. There is no filler or repetition of the schema.

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 5-parameter, no-output-schema tool at 0% schema coverage, this covers the essentials including return value and per-provider behavior. Marginal gaps remain: it does not clarify how the required `text` field interacts with fal prompt-based (music/SFX) models, nor what happens when no provider is configured.

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

Parameters5/5

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

Schema coverage is 0%, and the description compensates thoroughly: it explains the default provider resolution order, the default model and voice per provider, and precisely how the opaque `options` object is applied (merged into the request, shallow-updates generationConfig, becomes {prompt} for fal prompt-based audio). That is meaning the schema cannot convey.

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?

Opens with a specific verb+resource ('Text-to-speech ... Saves the audio file to disk and returns its path'), naming both the operation and its side effect. It is trivially distinguishable from generate_image, start_video, and check_video by modality.

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 provider breakdown gives concrete selection guidance (which backend is default, what each accepts, what output format results), so an agent knows how to pick a route. What is missing is an explicit when-to-use/when-not statement or a named alternative for overlapping cases (e.g. fal prompt-based music/SFX vs speech).

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

generate_imageA

Generate or edit an image. Saves full-resolution files to disk and returns paths plus a JPEG preview.

provider (default: first configured of openai, gemini, fal, cloudflare):

  • openai: default model gpt-image-2. aspect_ratio maps to size (1:1 -> 1024x1024; 16:9/3:2/4:3 -> 1536x1024; 9:16/2:3/3:4 -> 1024x1536). options merged into the request body (e.g. quality, background, n, output_format); options["size"] wins. input_images switches to /images/edits.

  • gemini: default gemini-3-pro-image (Nano Banana Pro). aspect_ratio -> imageConfig.aspectRatio (e.g. 16:9). options shallow-update generationConfig (e.g. imageConfig with imageSize).

  • fal: default fal-ai/nano-banana-pro. Input {prompt, aspect_ratio, image_urls} updated with options (model-specific params such as num_images, resolution, image_size). Any model id works.

  • cloudflare: default @cf/black-forest-labs/flux-1-schnell. Body {prompt} updated with options (e.g. steps, seed). No input_images.

input_images: local file paths, http(s) URLs or data URIs, used as edit targets or references.

ParametersJSON Schema
NameRequiredDescriptionDefault
modelNo
promptYes
optionsNo
providerNo
aspect_ratioNo
input_imagesNo

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does disclose the key side effect: files are written to disk and a preview plus paths are returned, so the agent knows this is not a read-only call. It also discloses the non-obvious branch where input_images switches openai to /images/edits. It omits auth requirements, cost, and failure modes for a paid generation endpoint.

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?

Front-loaded with purpose and return behavior, then a scannable per-provider bullet list. The density is justified by the zero schema coverage, though the provider bullets are heavy enough that an agent must read the whole block rather than skim.

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 6-parameter tool with no annotations, no output schema, and 0% schema description coverage, the description covers the provider/model/aspect_ratio/options/input_images surface and states what is returned. Gaps remain around error behavior, cost, and what happens when multiple providers are configured beyond the 'first configured' rule.

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

Parameters5/5

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

Schema coverage is 0%, so the description must compensate, and it largely does: aspect_ratio is given explicit per-provider mappings (1:1 -> 1024x1024, 16:9/3:2/4:3 -> 1536x1024), options merge semantics are spelled out including precedence ('options["size"] wins'), model defaults are named per provider, and input_images formats (paths, URLs, data URIs) and roles (edit target vs reference) are defined.

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?

Opens with a specific verb+resource ('Generate or edit an image') and immediately states the observable side effect and return shape ('Saves full-resolution files to disk and returns paths plus a JPEG preview'). This clearly separates it from siblings generate_audio, start_video, and check_video without needing their schemas.

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?

Provides clear selection context by documenting the provider default ('first configured of openai, gemini, fal, cloudflare') and the per-provider defaults (gpt-image-2, gemini-3-pro-image, fal-ai/nano-banana-pro, flux-1-schnell), plus when input_images switches to an edit path for openai. There is no explicit when-not guidance or cost/limit exclusion, but the provider routing context is unusually strong.

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

start_videoA

Start a video generation job (text-to-video, or image-to-video with input_image) and return its job_id immediately. Then call check_video(job_id) to wait for and fetch the result.

provider (default: first configured of openai, gemini, fal):

  • openai: default sora-2. aspect_ratio 16:9 -> 1280x720, 9:16 -> 720x1280. duration_seconds -> seconds. options merged into the request (e.g. size overrides). input_image sent as input_reference.

  • gemini: default veo-3.1-generate-preview. aspect_ratio and duration_seconds go to parameters.aspectRatio / durationSeconds; options merged into parameters (e.g. resolution, negativePrompt, personGeneration).

  • fal: default fal-ai/veo3.1/fast. Input {prompt, aspect_ratio, image_url} updated with options. Duration is model-specific on fal (e.g. "8s" vs "5"), so pass it via options such as {"duration": "8s"}; duration_seconds is rejected for fal.

input_image: local path, http(s) URL or data URI.

ParametersJSON Schema
NameRequiredDescriptionDefault
modelNo
promptYes
optionsNo
providerNo
input_imageNo
aspect_ratioNo
duration_secondsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and largely meets it: it discloses the asynchronous job_id contract, provider defaults, how duration_seconds and aspect_ratio are re-mapped per provider, that duration_seconds is *rejected* for fal, and that options are merged into the provider request. It omits auth requirements, rate limits, and prompt constraints, so not a 5.

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 first sentence front-loads the action and the async contract, followed by compact per-provider bullets. It is dense but every line carries operative detail; only minor trimming is possible.

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 7-parameter, no-annotation mutation tool this is thorough, and the job_id/polling contract plus provider quirks are covered. An output schema exists so return values need not be described, but there is no mention of validation limits or failure behavior, keeping it just short of complete.

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

Parameters5/5

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

Schema coverage is 0%, so the description must compensate, and it does: provider enumerates the three backends with defaults, aspect_ratio/duration_seconds translation is spelled out per provider, duration_seconds' fal constraint is documented, options is defined as provider-specific merged keys with examples, and input_image's accepted formats (path/URL/data URI) are given. This adds meaning far beyond the bare schema.

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?

States a specific verb+resource ('Start a video generation job') and immediately distinguishes the two modalities (text-to-video vs image-to-video via input_image). It also names the sibling it hands off to (check_video), so an agent can separate start from poll without opening either schema.

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?

Gives explicit workflow guidance: this tool returns a job_id immediately and check_video(job_id) must be called to wait for the result. It also provides per-provider selection guidance with defaults. It stops short of stating when *not* to use it (e.g. vs. generate_image/generate_audio), so a 4 rather than 5.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedcheck_video
    • First observedgenerate_audio
    • First observedgenerate_image
    • First observedstart_video

TDQS

A4.5/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct modality and action: generate_image (images), generate_audio (audio), and the start_video/check_video pair form a clearly documented async lifecycle. The start/check pairing is explicitly cross-referenced in both descriptions, so there is no risk of misselection.

Naming Consistency5/5

All four names follow a strict verb_noun snake_case pattern (generate_image, generate_audio, start_video, check_video). The verbs accurately reflect each tool's role, and the async pair uses a clean start/check convention rather than an inconsistent verb.

Tool Count5/5

Four tools is well-scoped for a media generation server covering image, audio, and video. Each tool earns its place: one per modality plus the necessary polling companion for the async video job.

Completeness4/5

The core generation lifecycle for images (including edits via input_images), audio (including prompt-based fal models), and video is fully covered. Minor gaps remain, such as no job cancellation, job listing, or file cleanup, but agents can work around these.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers