heygen-mcp
# heygen-mcp
MCP server for the [HeyGen](https://heygen.com) avatar video API. Provides tools that any
MCP-compatible client (Claude Desktop, Claude Code, etc.) can use to generate talking-avatar videos.
## Setup
```bash
cd heygen-mcp
npm install
```
Set your API key (HeyGen dashboard → Settings → API):
```bash
export HEYGEN_API_KEY="your-key-here"
```
Test the server starts correctly:
```bash
node index.js
# Should print "HeyGen MCP server running" to stderr
```
## Claude Desktop / Claude Code configuration
```json
{
"mcpServers": {
"heygen": {
"command": "node",
"args": ["/Users/carlosvidal/www/heygen-mcp/index.js"],
"env": { "HEYGEN_API_KEY": "your-key-here" }
}
}
}
```
Or from the CLI:
```bash
claude mcp add heygen -e HEYGEN_API_KEY=your-key-here -- node /Users/carlosvidal/www/heygen-mcp/index.js
```
## Tools
### create_video
Primary tool. Submits the video, polls until rendering finishes, returns the `video_url`, and
optionally saves the mp4 to `output_path`.
**Params:** `avatar_id`, `text`, `voice_id`, `talking_photo_id`, `audio_url`, `avatar_style`,
`speed`, `emotion`, `locale`, `background`, `scenes`, `dimension`, `title`, `caption`,
`output_path`, `timeout_seconds`
### generate_video
Submits the video and returns `video_id` immediately, without polling.
**Params:** same as `create_video` minus `output_path` / `timeout_seconds`
### check_video
Status of a video by `video_id` — `pending`, `waiting`, `processing`, `completed` or `failed`.
Returns `video_url`, `thumbnail_url`, `gif_url`, `caption_url` and `duration` when completed.
### download_video
Saves a finished video to a local `.mp4`. Accepts `video_id` (URL looked up automatically) or a
direct `video_url`.
### list_avatars
Search avatars by name or ID. **Always pass `search`** — an account holds well over a thousand
avatars. Set `include_talking_photos` to also match photo avatars.
### list_voices
Search voices by `search` / `language` / `gender`. Returns `voice_id`, `preview_audio`,
`emotion_support` and `support_locale`.
### list_videos
Recent videos in the account, to recover a `video_id` generated earlier.
### get_quota
Remaining API quota in seconds and credits. Run before long jobs.
## Single scene vs. multi-scene
A single scene uses the flat arguments:
```json
{ "avatar_id": "Piper_standing_education_front", "text": "Hola, soy Piper.", "voice_id": "1eca26cb..." }
```
Multiple scenes use `scenes`, which overrides the flat arguments. Each scene has its own avatar,
script, voice and background:
```json
{
"scenes": [
{ "avatar_id": "avatar_a", "text": "Primera escena.", "voice_id": "voice_a",
"background": { "type": "color", "value": "#f5f5f5" } },
{ "avatar_id": "avatar_b", "text": "Segunda escena.", "voice_id": "voice_b",
"background": { "type": "image", "url": "https://example.com/bg.jpg" } }
],
"dimension": "1080p_portrait",
"title": "Demo"
}
```
## Dimension presets
| Preset | Size |
|---|---|
| `1080p_landscape` | 1920x1080 |
| `720p_landscape` (default) | 1280x720 |
| `1080p_portrait` | 1080x1920 |
| `720p_portrait` | 720x1280 |
| `square` | 1080x1080 |
## Notes
- Video URLs expire **7 days** after generation — use `output_path` or `download_video` to keep them.
- Max **1500 characters** of `text` per scene; split longer scripts across scenes.
- HeyGen bills 1 credit per 60 seconds of rendered video.
- Rendering typically takes 1–3 minutes; polling interval is 5 seconds, default timeout 300s.
- `emotion` only applies to voices with `emotion_support: true`; `locale` only to voices with
`support_locale: true`.
TDQS
Scored across 8 tools
create_video and generate_video are nearly synonymous in name and purpose—both trigger video generation, differing only in synchronous vs. asynchronous behavior. check_video and list_videos also have some overlap in tracking video status, though their intent is clearer.
All tools follow a consistent verb_noun snake_case pattern (list_avatars, create_video, check_video). No camelCase, no mixed verb styles, and each verb clearly maps to the action performed.
With 8 tools, the set is well-scoped for the HeyGen video-generation domain: two video creation paths, status checking, download, quota, and resource listing. Each tool serves a distinct need without bloat.
The core lifecycle is covered: list avatars/voices, create video (both sync and async), check status, download result, and list history. Quota checking prevents dead ends. No obvious missing operations for a video generation API.