Skip to main content
Glama

HeyGen Video MCP

A stdio MCP server that lets Codex, Claude Desktop, and other MCP agents generate videos with heygen/heygen-video-1 on OpenRouter. Python 3.11+ and uv are required. It uses the official MCP Python SDK.

Install

git clone https://github.com/stevenke1981/heygen-video-mcp.git
cd heygen-video-mcp
uv sync --locked
uv run heygen-video-mcp

Set OPENROUTER_API_KEY in the launching process environment or your host's secret store. The server does not load .env automatically. Never paste secrets into prompts, commits, or command arguments. Optional HEYGEN_DATA_DIR selects persistent storage; its default is ~/.heygen-video-mcp.

Codex registration (replace the path with your clone's absolute path):

codex mcp add heygen-video -- uv run --directory /absolute/path/heygen-video-mcp --locked heygen-video-mcp

Generic MCP host configuration:

{
  "mcpServers": {
    "heygen-video": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/heygen-video-mcp", "--locked", "heygen-video-mcp"]
    }
  }
}

The host must inherit OPENROUTER_API_KEY. On Windows, use an absolute uv.exe path if the host cannot find it; JSON paths need escaped backslashes. Restart/reload your MCP host after registration. Local agents need access to the same data directory to resume jobs.

For a Windows NAS/mapped-drive checkout, put the virtual environment on a local disk: set UV_PROJECT_ENVIRONMENT=C:\Users\YOUR_USER\.cache\heygen-video-mcp\venv both when running uv sync and in your MCP host environment. This avoids native DLL loading failures from UNC paths.

Related MCP server: kairouter-mcp

Agent workflow

  1. Call heygen_estimate with request (prompt, duration, resolution, aspect_ratio, optional seed). This only reads the public model catalog.

  2. Explain the selected model, purpose, USD rate and estimated total to the user. Obtain explicit consent for this paid call.

  3. Call heygen_submit with the same request, a unique request_key, the actual user consent in approval, and their max_cost_usd. This checks current pricing again and sends one POST.

  4. Poll heygen_status(job_id) about every 30 seconds. Continue an existing job after a timeout; never automatically regenerate.

  5. Call heygen_download(job_id, filename) after completion. Inspect the actual MP4 before claiming creative approval.

heygen_receipt(request_key) recovers the locally saved job ID. Repeating submit with the same key and parameters returns the receipt without charging again. Changing parameters under a used key is rejected. Keep your ledger directory persistent. A different key is a different authorization responsibility, not provider-side idempotency.

Submission failure leaves an UNKNOWN receipt. Check OpenRouter activity/support before any retry; a timeout does not prove the provider rejected the job. The current API has no documented idempotency header or lookup-by-local-key endpoint. Receipts contain prompts and consent and should be kept private.

HTTP failures retain their status and redacted response text in the local receipt so parameter or account errors can be diagnosed without another paid request. API keys and response URLs are removed from these diagnostics. Reconciliation and renewed approval are still required before another submission.

Cost and feature scope

This release supports text-to-video, 5–15 seconds, 480p/768p/2K and the six advertised aspect ratios. It validates capabilities against the live catalog. It intentionally exposes one model and no model-routing fallback. Reference inputs and separate voice generation are outside this release.

HeyGen Video 1 always renders an audio track. Its live generation endpoint rejects generate_audio: false, despite the discovery catalog currently advertising that value. This server therefore omits the audio toggle and uses the provider's native behavior. Ask for silence or suitable sound in the prompt; this is not a guaranteed mute control. Listening review is separate from decoding.

Prices are fetched at execution time from GET /videos/models. On 2026-10-31, 768p was listed at $0.036/second ($0.18 for five seconds), while the web model page advertised a 50% discount. Estimates use the undiscounted SKU price. max_cost_usd is a local estimate gate, not a billing cap enforced by OpenRouter. It cannot guarantee final charges; use provider account/key spending controls as well. The consent field is a workflow record, not authentication of a human approval.

The tools do not log API keys or return signed asset URLs. Downloads use the fixed OpenRouter content endpoint; HTTPX removes Authorization across origins. Downloads refuse existing files, retain incomplete .part files, and return a SHA256. An MP4 signature is only a format check, not full media validation.

Children's example: 老鼠娶親

examples/mouse-wedding.json is a five-second 768p, 16:9 prompt: a friendly mouse wedding procession, red embroidered clothes, lanterns, flower petals and a sunny village. No frightening animals, chasing, violence, fireworks or readable generated text. It is a prompt, not a generated result.

Use the included MCP client to preview tools and estimate, without a paid call:

uv run python examples/client.py

After actual user approval, the same client can submit through MCP:

uv run python examples/client.py --submit --approval "ACTUAL USER CONSENT" --max-cost-usd 0.18
uv run python examples/client.py --status JOB_ID
uv run python examples/client.py --download JOB_ID

The example uses the stable request key mouse-wedding-v1. Do not change it to bypass an uncertain receipt.

Development

uv sync --locked --group dev
uv run pytest
uv run ruff check .
uv build

Tests mock external generation; the stdio test launches the real server and checks MCP discovery and invalid arguments without charging. CI never receives an OpenRouter key. Live generation requires separate consent.

Sources

MIT license. This community project is not affiliated with HeyGen or OpenRouter. The license covers this code, not provider service terms or generated-media rights.

Available Tools

5 tools
heygen_downloadA

Download an existing completed job into HEYGEN_DATA_DIR/outputs; never overwrite. Returns local path and SHA256. No new generation.

NameRequiredDescriptionDefault
job_idYes
filenameNovideo.mp4

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior4/5

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

Adds real context beyond the annotations: it writes into a specific directory, refuses to overwrite, and reports a local path plus SHA256 for integrity checking. That 'never overwrite' guarantee is exactly the behavior an agent needs, though it doesn't say whether a collision raises an error or picks a new name.

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 short clauses, each earning its place: action plus destination, the overwrite guarantee, and the return value. Front-loaded with no filler.

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?

Output schema exists so return values needn't be spelled out, but two gaps remain for a tool that writes to disk: behavior when the target file already exists, and behavior when the job isn't complete yet. The filename parameter's role is left entirely implicit.

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

Parameters2/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 carry both parameters, and it explains neither. job_id is only indirectly constrained by 'completed job', and the filename parameter (default video.mp4) — the one that interacts with the 'never overwrite' rule — is never mentioned.

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?

States a specific verb and resource ('Download an existing completed job') plus the destination ('HEYGEN_DATA_DIR/outputs'), and the closing 'No new generation' rules out the generation siblings like heygen_submit. It never names heygen_status or heygen_receipt, so differentiation is by negation rather than explicit routing.

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?

'existing completed job' implies a precondition (the job must already be finished) but never tells the agent to verify via heygen_status first, nor what to do if the job is still running. No alternatives are named; usage is inferable rather than stated.

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

heygen_estimateB
Read-only

Fetch current capabilities and conservative USD SKU estimate. No generation or charge. Text-to-video only.

NameRequiredDescriptionDefault
requestYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=true; the description reinforces this with a no-charge, no-generation guarantee and a modality restriction ('text-to-video only'), which is real added context. It doesn't say whether the estimate is deterministic or how the 'conservative' bound is derived, which keeps it below 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?

Three short, front-loaded sentences with no filler; the safety guarantee follows immediately after the purpose. Slight loss for the jargon-heavy 'conservative USD SKU estimate' phrasing that needs unpacking.

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?

An output schema exists, so return values needn't be explained, and annotations cover the safety profile. But with five nested parameters at 0% schema coverage, the description should say at least which fields affect the estimate and what 'capabilities' returns.

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

Parameters2/5

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

Schema description coverage is 0% and the nested VideoRequest exposes prompt, duration, resolution, aspect_ratio, and seed with no explanation anywhere. The description never mentions that duration/resolution drive the SKU estimate, so an agent gets no help mapping inputs to price.

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 names a specific action (fetch capabilities and a USD SKU estimate) and scopes it to text-to-video, which separates it from heygen_submit's generation role via 'No generation or charge.' 'Capabilities' remains vague, but the verb+resource pairing is clear enough to select the tool.

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 'No generation or charge' clause implies this is the pre-flight/dry-run option before heygen_submit, but the description never says 'use this before submitting' or names the sibling explicitly. Usage is inferable rather than stated.

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

heygen_receiptA
Read-only

Read the saved request and job ID without generating again. UNKNOWN requires dashboard reconciliation.

NameRequiredDescriptionDefault
request_keyYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior4/5

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

The description adds meaningful behavioral context beyond the readOnly annotation: it confirms no generation occurs and notes that an UNKNOWN result requires dashboard reconciliation. It does not explain what UNKNOWN refers to or what the receipt includes, but the annotations already cover the safety profile.

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 two short sentences with no wasted words, and the core action is front-loaded. The UNKNOWN reconciliation note is compact even if slightly cryptic.

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?

Output schema and read-only annotations mean return values and safety need not be re-explained, but the missing definition of 'request_key' and the cryptic UNKNOWN note leave gaps for a tool whose only parameter is undocumented. The description is minimal but not quite complete for reliable invocation.

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

Parameters2/5

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

Schema description coverage for the sole parameter is 0%, and the description never explains what 'request_key' represents, where to obtain it, or how it relates to the saved request. The phrase 'saved request' is suggestive but does not compensate for the missing schema documentation.

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 uses a specific verb ('Read') and resource ('saved request and job ID') and clarifies it does not regenerate content. It is clear enough to distinguish from heygen_submit, but it does not explicitly differentiate from heygen_status or heygen_download.

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?

Usage is implied by 'without generating again' and the UNKNOWN reconciliation note, but the description does not explicitly say when to use this versus heygen_status, heygen_submit, or heygen_download. The agent must infer the context from the sibling names.

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

heygen_statusB
Read-only

Poll once. Wait about 30 seconds between polls. Terminal failures must not trigger automatic regeneration.

NameRequiredDescriptionDefault
job_idYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered; the description adds genuinely new behavior — single-shot polling semantics, a recommended interval, and explicit handling of terminal failures. It stops short of describing job states or whether repeated polling has limits.

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?

Three short sentences, front-loaded with the action, then cadence, then the failure rule. Every sentence carries information, though the terseness borders on under-specification.

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?

An output schema exists so return values need not be explained, but the description omits where job_id comes from and how this step fits the submit → status → download flow. For a polling tool in a multi-step pipeline that is a meaningful gap.

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

Parameters2/5

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

The single required parameter job_id has 0% schema description coverage — only a regex pattern — and the description never mentions it, its provenance (from heygen_submit), or its format. With one undocumented parameter the description is expected to compensate and does not.

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

Purpose3/5

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

"Poll once" implies a status check, but the description never names the resource being polled (a HeyGen generation job) or what a poll returns. Combined with the name heygen_status the intent is inferable, but it is not a stated verb+resource, and it draws no boundary against heygen_receipt or heygen_download.

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?

It gives concrete operational guidance — poll once, ~30s between polls — and a guardrail against auto-regeneration on terminal failure. What is missing is routing: nothing says when to call this instead of heygen_receipt, or what to do after a successful/non-terminal poll.

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

heygen_submitA
Idempotent

PAID: submit once AFTER explicit user approval. Record the user's consent in approval and their USD limit. Never invent either. Reuse request_key to recover a receipt; uncertain submissions must be reconciled manually.

NameRequiredDescriptionDefault
requestYes
approvalYes
request_keyYes
max_cost_usdYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior5/5

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

The description adds substantial behavioral context beyond the annotations: the call is PAID, requires explicit user approval, must record consent and a cost ceiling, must never invent either, and uses request_key for idempotent receipt recovery. These details align with idempotentHint=true and openWorldHint=true and tell the agent exactly how to behave around a costly, state-changing submission.

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 short sentences, front-loaded with PAID and the one-time approval requirement. Every sentence carries distinct operational value: approval, cost limit, and request_key reconciliation.

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 is complete for the critical behavioral aspects of a paid, idempotent submission, and output details are covered by the output schema. The main remaining gap is that it does not point the agent to heygen_estimate for determining max_cost_usd, nor does it explain the request payload fields.

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 0% schema description coverage, the description does important semantic work for approval, max_cost_usd, and request_key, clarifying consent, spending limit, and idempotency. However, it says nothing about the request object or its fields such as prompt, duration, resolution, and aspect_ratio, leaving the main payload undocumented.

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 a specific action—submitting a paid request—but does not explicitly name the resource as video generation; that is inferred from the schema and sibling names. It distinguishes itself from retrieval siblings by emphasizing one-time paid submission and request_key receipt recovery.

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 gives strong usage constraints: submit once, only after explicit user approval, with recorded consent and a USD limit. It also mentions reusing request_key for receipt recovery and manual reconciliation for uncertain submissions, though it does not explicitly route the agent to heygen_estimate before setting max_cost_usd.

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. 5 tool updatesv0.1.0
    • First observedheygen_download
    • First observedheygen_estimate
    • First observedheygen_receipt
    • First observedheygen_status
    • First observedheygen_submit

TDQS

A3.8/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct role in the paid video-generation workflow: estimate, submit, recover receipt, poll status, and download. The descriptions sharply separate actions that might otherwise overlap, such as submit versus receipt and status versus download.

Naming Consistency4/5

All tools use the same heygen_ prefix and readable snake_case, which keeps the set predictable. However, the suffix pattern mixes verbs (submit, download, estimate) with nouns (receipt, status), so it is not a strict verb_noun convention.

Tool Count5/5

Five tools are well scoped to the single-video generation lifecycle, with no redundant or trivial tools. Each tool earns its place by covering a specific stage from cost estimation through download.

Completeness5/5

The surface covers the full core workflow for paid HeyGen generation: estimate cost, submit with approval, recover a saved receipt, poll status, and download a completed result. Optional extras like cancellation or listing jobs are not essential for the stated per-request lifecycle.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers