# How to Make a Changelog Video Automatically with Claude Code or Codex (MCP)


You can make a changelog video automatically by connecting Claude Code or Codex to a video MCP server and asking the agent to turn your latest release into a video. The agent reads the commits, writes a short JSON spec (screenshots, title, script, look, captions, format), checks a preview frame, and renders an MP4 for the release notes and a GIF for the README. A 12-second clip per feature takes a few minutes, and nobody opens a timeline editor.

Below is the setup with [Lumora](/)'s MCP server (ours), with a full example spec. The spec is illustrative: field names match our `create_video` tool, but the values are made up. The [agent docs](/docs/agents) have the full reference.

## Why make changelog videos at all?

Release notes are text, and most users skim them. A short clip of the new screen, with one sentence of narration, shows the change faster than a paragraph. The same clip works on X, LinkedIn and in the in-app changelog.

Most teams don't make them because each one costs an hour in an editor. Once an agent can produce a decent first cut from the code it just shipped, that cost drops to reviewing a preview.

## How does an agent make a video over MCP?

The [Model Context Protocol](https://modelcontextprotocol.io/specification/draft/basic/transports) lets an AI client call tools on a server. Over the Streamable HTTP transport, each message is an HTTP POST to a single endpoint. Our hosted server lives at `/mcp` on your account's address and takes a Bearer API key.

The tools the agent gets:

| Tool | What it does |
|---|---|
| `list_styles` | Looks, camera moves, palettes, effects, formats and music you can use |
| `upload_media` | Upload a screenshot, recording or audio file from a URL or base64 |
| `create_video` | Create a video project from a JSON spec |
| `update_video` | Change fields on an existing project |
| `get_video` / `list_videos` | Read a project's full JSON / list your projects |
| `preview_frame` | Render one frame as an image so the agent can check it |
| `render_video` | Export MP4, GIF or WebM |
| `render_status` | Poll a render that's still running |

The loop is: **list_styles → upload_media → create_video → preview_frame → (update_video) → render_video**.

## How do you connect Claude Code?

First create an API key in your account settings, under API keys for agents. Then run:

```bash
claude mcp add --transport http lumora https://lumora.video/mcp \
  --header "Authorization: Bearer lum_..."
```

That's the documented [Claude Code syntax for remote HTTP servers](https://code.claude.com/docs/en/mcp). By default the server is added for you in the current project only. Add `--scope project` to write it to `.mcp.json` so the whole team gets it. Keep the key out of the committed file: `.mcp.json` [expands environment variables](https://code.claude.com/docs/en/mcp) in `url` and `headers`, so each person sets their own.

```json
{
  "mcpServers": {
    "lumora": {
      "type": "http",
      "url": "https://lumora.video/mcp",
      "headers": { "Authorization": "Bearer ${LUMORA_API_KEY}" }
    }
  }
}
```

Claude Code asks for approval before using servers from `.mcp.json`.

## How do you connect Codex?

Codex reads MCP servers from `~/.codex/config.toml`. Per the [Codex MCP docs](https://learn.chatgpt.com/docs/extend/mcp?surface=cli), a Streamable HTTP server needs a `url`, and `bearer_token_env_var` names the environment variable that holds your key:

```toml
[mcp_servers.lumora]
url = "https://lumora.video/mcp"
bearer_token_env_var = "LUMORA_API_KEY"
```

Then `export LUMORA_API_KEY=lum_...` before starting Codex. There's also a plugin for Claude Code and Codex that bundles the server config with a skill for choosing styles. The [agent docs](/docs/agents) cover installing it.

## What goes in the video spec?

Here's an illustrative spec for one feature in a release. Field names are exact. The values, product and URLs are examples.

```json
{
  "name": "Pulse 2.4 release",
  "media": { "url": "/uploads/pulse-churn-alerts.png" },
  "brief": "Pulse now alerts you when churn spikes",
  "title": "Churn alerts",
  "tagline": "Know the day an account starts slipping",
  "look": "Launch day",
  "format": "landscape",
  "duration": 12,
  "script": "Pulse 2.4 adds churn alerts. Set a threshold, pick a channel, and Pulse pings you the day an account's usage drops.",
  "voice": true,
  "captions": "pop",
  "device": "macbook",
  "cta": { "text": "Try Pulse", "url": "https://example.com" }
}
```

What each field does:

| Field | Values | Notes |
|---|---|---|
| `media` | `{ "url": ... }` (an object, not an array) | The `url` is what `upload_media` returns. Add `"slides": [...]` for several screenshots |
| `brief` | One or two sentences | The AI direction reads the screenshot and writes callouts, camera moves and copy. Fields you set explicitly win |
| `title`, `tagline` | Text | Shown on the end card |
| `look` | e.g. `Launch day`, `Hype reel`, `Walkthrough` | 10 presets that set camera, palette and effects; `list_styles` has them all |
| `format` | `landscape`, `vertical`, `square` | 16:9, 9:16, 1:1 |
| `duration` | 5–60 seconds | The whole edit stretches to fit |
| `script` | Narration text | About 2 words per second; captions use it |
| `voice` | `true` or a voice id | Records the script with an AI voice |
| `captions` | `pop`, `clean`, `karaoke`, `off` | Burned in; renders also return an `.srt` |
| `device` | `macbook`, `ipad`, `iphone`, `android`, `macwindow`, `winwindow`, `none` | Laptop, tablet, phone or desktop-app window frame |
| `cta` | `{ "text", "url" }` | End card and a button on the share page |

The 12-second clip above has a 21-word script, which leaves room for the end card.

## What do you ask the agent?

Here is a prompt you can keep in the repo and reuse every release:

```text
Make a changelog video for the release we just tagged.

1. Read the commits and merged PRs since the previous tag. Pick the one
   user-facing feature that matters most.
2. Use the screenshot in docs/screens/ for that feature. Upload it.
3. Call list_styles, then create_video with look "Launch day",
   format landscape, 10–15 seconds, captions "pop", device "macbook",
   and a script under 30 words in plain language (no internal names).
4. Call preview_frame at 2s and 8s. If the callouts cover the wrong
   element or text is cut off, fix it with update_video.
5. Render an MP4 and a GIF. Put both links in the release notes draft.
```

Two habits make the output better:

- **Give it real screenshots.** The agent can't invent your UI. Keep a folder of current screens, or capture them in the same PR that changes them.
- **Make it look before it renders.** `preview_frame` returns an image, so the agent can see whether the callout points at the right button. That one check catches most bad first cuts.

## How do you render and publish?

`render_video` with `"format": "mp4"` gives a download URL, a public share link with view analytics, and an `.srt` caption file when the video has a script. Run it again with `"format": "gif"` for the README or changelog page. If a render takes longer than about 50 seconds, the tool returns a `renderId`, and the agent polls `render_status`.

Where the outputs go:

1. **GitHub release notes:** the GIF inline, linked to the MP4. Check the [GitHub size limits](/blog/demo-video-sizes-specs) first: 10MB for GIFs.
2. **In-app changelog:** the MP4 or WebM.
3. **X and LinkedIn:** run `update_video` with `"format": "vertical"` and render again for a 9:16 cut.

Rendering needs an account. On the free plan exports are 720p with a watermark (3 a month). Pro removes the watermark, renders 1080p and includes AI direction. Details are on [the homepage](/).

## What are the limits?

- **It doesn't record your screen.** You supply screenshots or a recording.
- **It doesn't zoom from recorded clicks.** Zooms and callouts come from the spec or the AI direction.
- **It's a video, not an interactive demo.** There are no clickable hotspots.
- **Review before publishing.** Treat the agent's cut as a draft. Check names, numbers and anything customer-facing.

For a full launch video rather than a release clip, the [product demo video guide](/blog/how-to-make-a-product-demo-video) covers structure and scripting, and the [Product Hunt launch video post](/blog/product-hunt-launch-video) covers launch-day specs.
