Skip to main content
Glama

dsh-media-mcp

中文 | English

Turn a sentence into an image or a short video on your machine.

dsh-media-mcp is a small MCP server. Your AI client calls it, it calls your media provider, and the result lands on disk as a normal file you can open. It also exposes its own settings as tools, so changing the model, the size or the output folder is something you say in chat — no settings screen to hunt for.

Works with any MCP client. Built for and tested with DeepSeek Harness (dsh).

What you can do

Just ask:

  • "Draw a corgi surfing at sunset." — you get back an absolute path to a saved JPEG.

  • "Make a five second clip of a paper boat drifting down a rainy street." — a video, in a few minutes (three to four, measured).

  • "What models are you using?" — get_config answers.

  • "Switch to Seedream 4.0, 2048x2048." — set_config saves it; the next image uses it.

Tool

What it does

generate_image

Generate from a prompt, save it, return the paths. Optional per-call model, size, outputDir.

generate_video

Generate a short clip. Text to video only. Optional per-call model, ratio, duration, outputDir. Slow and paid — ask for it explicitly.

get_config

Show the settings in effect, whether a key is configured, and which models are known.

set_config

Change a setting and save it. Applies to the next call.

It knows a size each image model will refuse, and says so before spending your money:

model doubao-seedream-4-5-251128 requires at least 3686400 pixels, but 1024x1024 is only
1048576. Retry with a larger size such as 1920x1920.

Related MCP server: ComfyUI MCP Server

Requirements

Node.js ^22.19.0 || >=24.0.0. No dependencies, no build step: clone it and run it.

Setup

1. Get an API key

The built-in preset is Volcengine Ark (Doubao / Seedream / Seedance). The server speaks the OpenAI images API for pictures and Ark's task API for video, so a different vendor works too — it needs one entry in src/providers.mjs.

2. Write the config file

This is where your key lives. ~/.config/media-gen/config.yml on macOS and Linux, or %APPDATA%\media-gen\config.yml on Windows:

provider: ark
apiKey: your-api-key
imageModel: doubao-seedream-5-0-flash-260915
imageSize: 1024x1024
videoModel: doubao-seedance-2-5-260628
# outputDir: "~/Pictures/generated"

Then chmod 600 it. config.example.yml is the same thing to copy from, and MEDIA_GEN_CONFIG points somewhere else if you prefer.

Quote a value that starts with ~, otherwise YAML reads it as nothing.

3. Point your client at the server

Any MCP client:

{
  "mcpServers": {
    "media": {
      "command": "node",
      "args": ["/absolute/path/to/dsh-media-mcp/src/server.mjs"],
      "cwd": "/absolute/path/to/your/workspace"
    }
  }
}

DeepSeek Harness — append this row to $DSH_HOME/profiles/<profile>/cordis.patch.yml. @deepseek-ai/dsh-mcp-client already ships with dsh, so nothing needs installing:

- insert:
    - id: mcp-media
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        transport: stdio
        serverName: media
        command: node
        args:
          - /absolute/path/to/dsh-media-mcp/src/server.mjs
        cwd: /absolute/path/to/your/workspace
        toolCallTimeoutMs: 900000   # a video waits minutes; the 60s default is far too short
        failOnStartupError: true

The tools appear as mcp__media__generate_image, mcp__media__generate_video, mcp__media__get_config and mcp__media__set_config.

No app restart needed: a patched profile picks the row up in the same session, and generated files follow cwd, so point cwd at the workspace you want them in.

Where your files go

What

Default

Override

Images

<workspace>/image_output/ — one img-YYYYMMDD-HHMMSS.jpg per result

outputDir (config or per call)

Videos

<workspace>/video_output/ — one vid-YYYYMMDD-HHMMSS.mp4 per result

outputDir (config or per call)

<workspace> is the cwd you gave the server. Setting outputDir sends both kinds to that one folder; leave it unset to keep them apart. media-gen outdir prints both directories, and ~ is expanded in a configured path.

Tools return paths, not file data, so a large image or clip never floods the conversation. Open the file with any viewer; in DeepSeek Harness you can also hand an image path to the read_image tool.

Settings

Change any of these with set_config, or by editing the file — it is read on every call, so nothing needs restarting either way.

Setting

In the config file

Environment variable

Notes

Provider

provider:

MEDIA_GEN_PROVIDER

Which preset to use. Default ark.

API key

apiKey:

MEDIA_GEN_API_KEY

Required. Never printed by any tool.

API URL

baseUrl:

MEDIA_GEN_BASE_URL

Overrides the preset's URL.

Image model

imageModel:

MEDIA_GEN_IMAGE_MODEL

Default model for pictures.

Image size

imageSize:

MEDIA_GEN_IMAGE_SIZE

Default size, WxH.

Video model

videoModel:

MEDIA_GEN_VIDEO_MODEL

Default model for clips.

Image timeout

imageTimeoutMs:

MEDIA_GEN_IMAGE_TIMEOUT_MS

Milliseconds one image call may take. Default 180000.

Video timeout

videoTimeoutMs:

MEDIA_GEN_VIDEO_TIMEOUT_MS

Milliseconds the whole video flow may take. Default 720000.

Output folder

outputDir:

MEDIA_GEN_OUTPUT_DIR

Overrides both defaults above. ~ is expanded.

An environment variable beats the config file. For the model lists, their size floors and their notes, run media-gen models or ask get_config.

Aspect ratio and clip length are per call (ratio, duration; default 16:9 and 5 seconds), because they change what a clip costs.

Timeouts

A five second clip measured about four minutes, so both waits are yours to set rather than constants baked into the code:

imageTimeoutMs: 300000     # a slow image provider
videoTimeoutMs: 1200000    # longer clips

set_config writes the same two keys, media-gen config set videoTimeoutMs=1200000 does it from a shell, and either can be overridden for one call: generate_image and generate_video take timeoutMs, the CLI takes --timeout-ms 1200000. get_config reports what is in effect.

The ceiling is 3600000 (one hour). A larger value is refused rather than shortened, because a call that hangs for an hour is a mistake worth seeing.

Keep your client's tool timeout above ours. The server can only stop its own wait; if your MCP client gives up first you get its error instead of a message naming the video task id. The DSH row above uses toolCallTimeoutMs: 900000 for that reason.

A config file from an older release, written as MEDIA_GEN_API_KEY=... lines, still works. Renaming it to config.yml is all it takes to move on.

Command line

The same server comes with a small CLI. Symlink bin/media-gen.mjs onto your PATH:

media-gen env                            # what is in effect right now
media-gen models                         # image models and their size floors
media-gen outdir                         # where images and videos will be written
media-gen img "a corgi surfing at sunset"
media-gen img "cyberpunk alley" -s 2048x2048 -o alley.jpg
media-gen video "a paper boat drifting down a rainy street" --duration 5
media-gen config set imageModel=doubao-seedream-4-0-250828
media-gen config set videoModel=doubao-seedance-1-0-pro-250528
media-gen key                            # redacted; the raw key is never printed
media-gen serve                          # run the MCP server on stdio

Troubleshooting

What you see

What it means

no API key configured

apiKey: is missing or empty in the config file.

model … requires at least N pixels

That image model has a size floor — use the size the message suggests.

media API error [InvalidEndpointOrModel.NotFound]

The model is not available to your account or region. get_config lists the models this version knows.

media API error [SetLimitExceeded]

Ark's "Safe Experience Mode" usage cap for that model. Raise or close it on the Ark console's model-activation page.

video task … did not finish within Ns

The clip was still rendering. The message carries the task id, so you can query it instead of paying for a second render — or raise videoTimeoutMs.

video task … reported a status this version does not know

A state the server will not guess at. Update the server rather than retrying blindly.

A video tool call is cut off by your client

Raise its tool timeout. The clip legitimately takes minutes; the row above uses 900000.

ignored: <key> in get_config

A config key that is not a setting — usually a typo, so it changed nothing.

format: env assignments — legacy

The file is in the old KEY=value style. It still works; rename it to config.yml whenever you like.

What video can and cannot do

Text to video, one clip per call. Reference images and videos (image-to-video, extend, edit) are not supported: each of those changes the request contract, and what is not implemented should not look like it is.

Development

Tests are offline — no network, no API key, no spend:

node --test tests/*.test.mjs

License

MIT — see LICENSE.

Available Tools

4 tools
generate_imageA

Generate an image from a text prompt and save it to disk. Call this when the user asks to draw, create, render, illustrate or generate a picture, photo or artwork. Returns the absolute paths of the saved files; pass one to read_image to view it. Each call costs real money, so call it once per explicit user request.

ParametersJSON Schema
NameRequiredDescriptionDefault
sizeNoOutput size as WxH, for example 1024x1024. Some models require at least 3686400 pixels, so 2048x2048 is the safe large size.
modelNoImage model id for this call only. Omit to use the configured default. Call get_config for the available ids and their size constraints.
promptYesWhat to draw, in natural language. Prefer a specific, visual description: style, subject, lighting and composition all help.
outputDirNoDirectory for this call only. Omit to use the configured default.
timeoutMsNoHow long this call may wait, in milliseconds. Omit to use the configured default. The ceiling is 3600000 (one hour).

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It discloses the side effect of saving to disk, the return format (absolute paths), how to view results (pass to read_image), and the cost implication. This is substantial coverage, though it omits potential timeouts or network behavior that could be relevant given the timeout parameter.

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?

Three sentences with zero fluff. The main action is front-loaded, the trigger conditions follow, and the return/cost note is placed at the end. Every sentence earns its place.

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

Completeness5/5

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

The description is complete for a generate-and-save tool. It explains the return value (paths), how to view results, and the cost constraint. The schema already covers all parameter details, so nothing essential is missing for an agent to call it correctly.

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 baseline is 3. The description adds no parameter-specific meaning beyond what the schema already documents; it only rephrases the purpose. It does not compensate for any schema gaps, as there are none, but it also adds no extra insight.

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 states a specific verb and resource: 'Generate an image from a text prompt and save it to disk.' It also lists trigger verbs (draw, create, render, illustrate, etc.) that clearly distinguish it from the video-generating sibling, making the purpose unmistakable.

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?

It explicitly states when to call ('when the user asks to draw, create, render...') and even adds a cost-based usage rule ('call it once per explicit user request'). However, it does not name alternatives or exclusions (e.g., don't use for video), so it lacks the explicit when-not guidance that would merit a 5.

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

generate_videoA

Generate a short video from a text prompt and save it to disk. Asynchronous: the provider renders in the background and this call waits, typically one to three minutes. Call it only when the user explicitly asks for a video — reference images and videos are not supported. Returns the absolute path of the saved file, the task id and how long it waited.

ParametersJSON Schema
NameRequiredDescriptionDefault
modelNoVideo model id for this call only. Omit to use the configured default. Call get_config for the available ids and their notes.
ratioNoAspect ratio as W:H, for example 16:9 or 9:16. Default 16:9.
promptYesWhat to film, in natural language. Describe the subject, the action and the camera movement: a shot the model can stage beats a list of keywords.
durationNoClip length in seconds. Default 5. Longer clips take longer and cost more; the provider decides which lengths it accepts.
outputDirNoDirectory for this call only. Omit to use the configured default, which is <workspace>/video_output.
timeoutMsNoHow long the whole call may wait — create, poll, download — in milliseconds. Omit to use the configured default. A five second clip measured about four minutes, so keep this generous; the ceiling is 3600000 (one hour).

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden. It discloses that the call is asynchronous and waits one to three minutes, that it saves to disk, and that it returns the absolute file path, task id, and wait duration. This is strong transparency, though it could also mention details like overwrite behavior or failure conditions.

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?

Three sentences with no fluff: purpose, async behavior, invocation condition, and return values are each covered. The most decision-relevant information is front-loaded, and every sentence earns its place.

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

Completeness5/5

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

For a tool with six parameters, no annotations, and no output schema, this description is complete enough for an agent to select and call it correctly. It explains the operation, the asynchronous waiting behavior, the supported input scope, and the return values, while the schema fully documents each parameter.

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?

Input schema coverage is 100%, so the baseline is 3. The description adds little parameter-specific meaning beyond the schema; it only reinforces that prompts are text-only via the unsupported-reference note. The schema descriptions themselves are already detailed, so no compensation is needed.

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 and resource: 'Generate a short video from a text prompt and save it to disk.' It also clearly distinguishes itself from sibling tools by stating that reference images and videos are not supported, which separates it from generate_image and any editing/referencing workflows.

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 gives explicit when-to-use guidance: 'Call it only when the user explicitly asks for a video.' It also specifies exclusions ('reference images and videos are not supported'), but it does not explicitly name alternative tools such as generate_image for image-generation cases, so it falls just short of full routing guidance.

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

get_configA

Report the current configuration: provider, base URL, the image and video models in use, their defaults, the output directory, whether an API key is present (never its value), and the catalogue of known models with their constraints. Call this before changing settings, or when the user asks which model is in use.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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

No annotations are present, so the description carries the full burden. It is read-only in nature ('Report'), and it discloses a meaningful behavioral detail: the API key's presence is reported but its value is never exposed. This is more than a minimal description, though it stops short of explicitly stating that it has no side effects.

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 dense but every clause adds information: what is reported, what is deliberately hidden, and when to call it. No filler or repetition exists.

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

Completeness5/5

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

With no parameters and no output schema, the description fully covers what an agent needs: it lists the returned configuration contents and the circumstances under which to invoke the tool. Nothing essential is missing.

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?

The tool has zero parameters, so the baseline is 4. The description doesn't need to add parameter meaning; instead, it appropriately explains what the tool returns, which is the relevant information for an agent.

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 ('Report') and a clear resource ('the current configuration'), then enumerates exactly what is included. The enumerated contents (provider, models, defaults, output directory, API key presence, model constraints) clearly distinguish this from the sibling generate_image, generate_video, and set_config tools.

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

Usage Guidelines5/5

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

It gives explicit when-to-use guidance: 'Call this before changing settings, or when the user asks which model is in use.' This tells the agent exactly when this tool is appropriate relative to set_config and the generation tools.

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

set_configA

Change settings and persist them to the config file. Call this when the user asks to switch a model, change a default size, output directory or timeout, or change provider. Only the fields passed are changed and everything else is preserved. Changes take effect on the next call with no restart.

ParametersJSON Schema
NameRequiredDescriptionDefault
apiKeyNoAPI key to store. Write-only: no tool ever returns it. Omit to keep the current key.
baseUrlNoAPI base URL override. Omit to use the provider default.
providerNoProvider id. Known: ark.
imageSizeNoDefault image size as WxH, for example 1024x1024.
outputDirNoDefault output directory. Set to an empty string to fall back to <workspace>/image_output.
imageModelNoDefault image model id.
videoModelNoDefault video model id. Video is generated only by an explicit generate_video call.
imageTimeoutMsNoDefault budget for one image call, in milliseconds. Raise it for a slow provider.
videoTimeoutMsNoDefault budget for the whole video flow, in milliseconds. A five second clip measured about four minutes.

TDQS

A4.2/5.0
Behavior4/5

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

No annotations are provided, so the description carries the full disclosure burden, and it does substantial work: it discloses persistence ('persist them to the config file'), partial-update semantics ('Only the fields passed are changed and everything else is preserved'), and effect timing ('Changes take effect on the next call with no restart'). It does not cover behavior on invalid values or error responses, which keeps it at a 4.

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?

Three sentences, each earning its place: the first states the core action, the second gives when-to-use triggers, the third clarifies semantics and effect timing. Information is front-loaded and there is zero filler or redundancy.

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 9-parameter, all-optional config tool with no annotations and no output schema, the description covers purpose, invocation triggers, persistence, partial-update behavior, and effect timing, while the schema fully documents every parameter. The main gap is the absence of any statement about return values or failure/validation behavior, but nothing critical for correct invocation is missing.

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 every parameter already carries a meaningful description in the schema itself, setting the baseline at 3. The description adds a small but useful cross-parameter semantic — 'Only the fields passed are changed' — clarifying that omitted parameters are preserved, but it does not need to and does not duplicate param-level detail.

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 states a specific verb and resource ('Change settings and persist them to the config file') and elaborates with concrete use cases: 'switch a model, change a default size, output directory or timeout, or change provider.' This clearly differentiates it from siblings generate_image and generate_video (generation tools) and get_config (read-only access), so an agent can distinguish them without opening 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?

The description gives explicit trigger conditions ('Call this when the user asks to switch a model, change a default size, output directory or timeout, or change provider'), which is clear, actionable guidance. It does not explicitly name get_config as the alternative for reading config or state when not to call the tool, so it stops short of the full 5, but the context is unambiguous.

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.2.0
    • First observedgenerate_image
    • First observedgenerate_video
    • First observedget_config
    • First observedset_config

TDQS

A4.4/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct operation: image generation, video generation, config retrieval, and config modification. No overlap exists, making selection unambiguous.

Naming Consistency5/5

All tools follow the verb_noun pattern: generate_image, generate_video, get_config, set_config. The naming is consistent and predictable.

Tool Count5/5

With 4 tools, the server is well-scoped for its purpose—media generation plus configuration management. Each tool is essential and there are no redundant or missing core operations.

Completeness4/5

The core generation and configuration workflows are covered, but the reference to a read_image tool in generate_image's description suggests a potential gap for viewing outputs. No explicit file listing or deletion tools are present, though these may be outside the server's intended scope.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers