← Home
CLI GUIDE

By Valmera Editorial · Published · Updated

Edit Video from Claude Code

Add Valmera to Claude Code as a remote HTTP MCP server and the session that writes your code can also cut a screen recording: upload the file from disk, remove the dead air, caption it, reframe it to 9:16, render, and drop the review MP4 into ./dist. The source-quality final is created in Studio. One command and one browser sign-in.

This page is the CLI. For the Claude app's connector UI — the same server, no commands — see connecting Claude to video editing.

RUN THIS
claude mcp add --transport http valmera \ https://entrepreneur-bot-backend.onrender.com/mcp

Then /mcp inside Claude Code to sign in. Streamable HTTP · OAuth 2.1 with dynamic client registration and PKCE · 100+ live tools.

Why the Terminal Is Where This Belongs

Most of the video a developer produces is made a few feet from the code. Screen recordings of a bug. A demo of the feature that just merged. The forty-second clip that goes in the release notes. A walkthrough for the docs site. That footage is already on the machine Claude Code is running on, and the finished file has to end up in a repo, a release asset or a CDN bucket — which is also where Claude Code already is.

The mechanical reason the pairing works is narrower and more interesting. MCP arguments are JSON, so video bytes never cross the protocol. Valmera's upload_start therefore hands back a presigned URL and the literal command to push the file to it. A chat app cannot run that command — you run it. A terminal agent runs it itself. That single difference is what turns "upload this and cut it" from a two-tool conversation with a manual step in the middle into one uninterrupted sentence.

And a scripted edit is closer to a build step than a creative session. "Cut the silences, caption it, 9:16, save the review preview to dist" is a request you will make again next release, on next month's recording, with the same wording. That belongs in a CLAUDE.md or a slash command next to your other repeatable jobs. The request repeats exactly; the edit is still an agent's judgement each time, which is worth remembering before you wire it into a pipeline nobody watches.

How to Connect Valmera to Claude Code

  1. 1
    Create a Valmera account
    Sign up free at valmera.io with email or Google. Account creation and uploads are free, but agent editing requires a subscription. If you signed up with Google, set a password with "Forgot password" first — the OAuth consent screen needs one. MCP access is included automatically with an active Valmera Pro or Frontier subscription. If an earlier attempt was refused, reconnect using your verified subscriber email.
  2. 2
    Add the server
    Run: claude mcp add --transport http valmera https://entrepreneur-bot-backend.onrender.com/mcp. Add --scope user to make it available in every repo, or --scope project to write a committed .mcp.json for your team. With no flag it is local scope: this repo, you only.
  3. 3
    Authenticate
    Start Claude Code and run /mcp, then follow the browser sign-in and press Allow. Claude Code discovers the authorization server from the endpoint and registers itself — there is nothing to paste. From v2.1.186 you can run claude mcp login valmera from the shell instead, and from v2.1.191 it detects an environment with no browser — an SSH session, a Linux box with no display server — and prints the authorization URL to open elsewhere; --no-browser forces that prompt even when a browser is present. Either way the paste step needs an interactive terminal, so connect with ssh -t.
  4. 4
    Confirm it connected
    Run claude mcp list. A working server reads ✔ Connected; ! Needs authentication means step 3 has not completed; ✘ Failed to connect is a transport or credential problem. Inside a session, /mcp shows the tool count next to the server.

One command and one sign-in. The first upload then needs a one-time analysis pass — transcript, silences, shot boundaries and frame tiles — which reports progress and is reused by every edit afterwards.

Local, Project or User Scope

claude mcp add writes the server somewhere, and the flag decides where. The default is local, which surprises people who expected the server to follow them between repos.

LocalProjectUser
Flag--scope local (default)--scope project--scope user
Loads inThis repo onlyThis repo onlyEvery repo on your machine
Stored in~/.claude.json.mcp.json in the repo root~/.claude.json
Committed to git
Teammates get it
Use it whenTrying it outThe repo ships videosIt is your editor, everywhere

When the same server name is defined at more than one scope, Claude Code connects once and uses the entry from the highest-precedence source — local, then project, then user. The whole entry wins; fields are not merged across scopes. So a local valmera with a stale token quietly shadows the correct project-scoped one, and claude mcp get valmera is how you find out which definition is live.

Pick user scope if Valmera is simply your editor. Pick project scope if the repo itself ships video — a docs site, a marketing site, a product with release demos — because then the tooling belongs to the repo rather than to whoever happened to set it up.

A Committed .mcp.json for a Team

Project scope writes a standard file at the repo root. Commit it:

claude mcp add --transport http valmera --scope project \
  https://entrepreneur-bot-backend.onrender.com/mcp

.mcp.json

{
  "mcpServers": {
    "valmera": {
      "type": "http",
      "url": "https://entrepreneur-bot-backend.onrender.com/mcp"
    }
  }
}

Three things about this file are worth stating plainly.

It carries no credential. The endpoint is shared; the identity is not. Each teammate runs /mcp and signs in as themselves, against their own Valmera account, their own projects and their own credits. Nobody inherits anyone else's footage by cloning a repo.

Every teammate is asked before it is used. Claude Code prompts for approval before running a server defined in .mcp.json, and a pending one shows in claude mcp list as ⏸ Pending approval until someone runs claude interactively and answers. claude mcp reset-project-choices clears that answer. A cloned repo cannot approve its own servers, which is the point.

The type field is not optional. An entry with a url and no type is read as a stdio server and skipped, with MCP server "valmera" has a "url" but no "type". If you hand-edit the file, keep "type": "http" (streamable-http is accepted as an alias, so configs copied from other servers' docs work unchanged).

The Bearer Token Path

OAuth is the better path when there is a person and a browser. There often is not — a CI runner, a container, a client that never implemented the OAuth half of the spec. For those, the server also accepts a static token on the standard header:

claude mcp add --transport http valmera \
  https://entrepreneur-bot-backend.onrender.com/mcp \
  --header "Authorization: Bearer vlm_mcp_..."

Tokens are issued once and stored only as a sha256 hash, so a lost one is replaced rather than recovered. Both credential types resolve to the same thing inside the server — who you are, and which project is open — so a token session and an OAuth session get an identical tool registry and identical refusals.

One asymmetry to know before you choose this path: if headers.Authorization is set and the server rejects it, Claude Code reports the connection as failed rather than falling back to OAuth. So a revoked token looks like a transport problem. Remove the header if you want the browser flow back.

Never commit the token. Claude Code expands environment variables inside headers and url, so a shared .mcp.json can reference a secret each developer supplies for themselves:

.mcp.json

{
  "mcpServers": {
    "valmera": {
      "type": "http",
      "url": "https://entrepreneur-bot-backend.onrender.com/mcp",
      "headers": {
        "Authorization": "Bearer ${VALMERA_MCP_TOKEN}"
      }
    }
  }
}

An unset variable does not fail the load — Claude Code warns in claude mcp list and leaves the literal ${VALMERA_MCP_TOKEN} in place, which then fails authentication with unknown or revoked token. Use ${VAR:-default} if you want a fallback.

A Session, End to End

A 90-second screen recording of a feature that just shipped, at ~/screencaps/v2-release.mov. The goal is a captioned vertical cut in ./dist. Here is the whole thing, with the tool calls the model makes shown between the two sides of the conversation.

$ claude mcp add --transport http valmera \
    https://entrepreneur-bot-backend.onrender.com/mcp
Added HTTP MCP server valmera to local config

$ claude
> /mcp
  valmera   ! Needs authentication  →  Authenticate
  … browser opens, sign in, Allow …
  valmera   ✔ connected · 100+ live tools
> Make a Valmera project from ~/screencaps/v2-release.mov, cut the
  silences and the ums, caption it in the podcast preset, reframe it
  to 9:16, then save the review preview into ./dist.

⏺ create_project(title: "v2-release")
    Project 4127 created and active.

⏺ Bash(stat -f%z ~/screencaps/v2-release.mov)
    12648430

⏺ upload_start(filename: "v2-release.mov", size_bytes: 12648430)
    Upload the file with this exact command, then call upload_finish(…)
    curl -sS -f -X PUT -H 'Content-Type: video/quicktime' \
      --upload-file '<LOCAL PATH>' 'https://…'

⏺ Bash(curl -sS -f -X PUT -H 'Content-Type: video/quicktime' …)
    (12.6 MB uploaded)

⏺ upload_finish(storage_key: "…", filename: "v2-release.mov")
    Uploaded (asset 9312). Analysis started as job 8811 — the
    transcript, shots and silences do not exist until it finishes.

⏺ index_status()
    running — 58% (job 8811).

⏺ index_status()
    done — the video is analyzed and ready to edit.

Those two Bash lines are the whole argument for doing this from a CLI. In the Claude app they are your job, in another window.

⏺ cut_silences()
    17 silences removed. Program 91.4s → 68.2s.

⏺ remove_filler_words()
    9 fillers removed (um ×6, uh ×2, you know ×1).
    Program 68.2s → 66.9s.

⏺ add_captions(mode: "from_transcript", style: {preset: "podcast"})
⏺ auto_reframe(ratio: "9:16")

⏺ render_preview()
    STILL RUNNING — render_preview is job 8814 (running, 12%). Nothing
    has failed; call wait_for_job(job_id=8814) to pick the result up.

⏺ wait_for_job(job_id: 8814)
    STILL RUNNING — job 8814 (mcp_tool) (running, 71%).

⏺ wait_for_job(job_id: 8814)
    Preview of EDL v6 rendered.

⏺ look_at(output_times: [2.4, 19.8, 44.1, 63.0])
    … four frames, read by the model …

That look_at call is the agent checking its own work. It gets real frames out of the preview it just rendered — captions in place, the crop where it landed — rather than reporting what it intended to do. On this footage it is the step that catches a caption sitting over the toolbar you were demonstrating.

⏺ watch_video(project_id: 42)
    Review handoff opened for the complete preview of EDL v6.

⏺ download_url(project_id: 42, kind: "preview")
    preview of EDL v6 — https://… (link valid a few hours)

⏺ Bash(mkdir -p dist && curl -sS -o dist/v2-release-9x16.mp4 'https://…')

  Review preview saved to dist/v2-release-9x16.mp4 — 66.9s, 9:16.
  The edit is ready; create the source-quality final in Valmera Studio.

Two details in that last line are load-bearing. The preview renders from a fast proxy because it has to be quick. When you approve the edit and create the final in Studio, that render goes back to the file you uploaded and runs at source quality. And nothing in the sequence touched your .mov — every tool wrote to an edit decision list, which is why any of it can be reversed by asking.

How Renders Behave: wait_for_job

The one part of this that reads oddly the first time. A render is minutes of ffmpeg; an MCP tool call is a request. Something has to give, and what gives is the pretence that the call finished.

Every call returns inside about 25 seconds

That bound is deliberate. Claude Code puts a 60-second timer on the first response byte from an HTTP MCP server, so a tool that blocked for the length of a render would be killed by the client rather than finished by the server. Valmera waits ~25 seconds for the job, then answers with whatever is true at that moment.

STILL RUNNING is a receipt, not an error

A preview render, burned-text erasure or a generated clip can come back as: STILL RUNNING — render_preview is job 8814 (running, 12%). Nothing has failed; call wait_for_job(job_id=8814) to pick the result up. The job is queued server-side and keeps going whether or not anything is waiting on it.

wait_for_job is meant to be called in a loop

It waits a bounded time too, and returns either the finished result or the same line at a higher percentage. There is no penalty for calling it repeatedly, and no state is lost between calls — the job id is the whole handle.

Three jobs per account at once

A fourth is refused with "Too much is already running on this account — wait for it to finish and try again." This matters more from a CLI than from a chat window, because a scripted run can fire off preview renders faster than they finish.

A preview is a link; final export is Studio-only

download_url(kind="preview") mints a temporary URL for the rendered review file, so Claude Code can curl that preview into ./dist/. It cannot create a source-quality final export: that last action is deliberately Studio-only, and download_url(kind="final") can only retrieve an export that already exists.

Claude Code has its own safety net underneath this: a main-conversation MCP call still running after two minutes moves to a background task rather than blocking the session (v2.1.212+). Valmera's 25-second bound means you will rarely see it fire. If you want a longer ceiling for a specific reason, set "timeout" in milliseconds on the server's .mcp.json entry — it is a hard wall-clock limit per call, and progress notifications do not extend it.

One Project, One Editor

If the studio is open on the same project in a browser tab, an MCP tool call answers:

Valmera's own agent is mid-turn on this project — wait for it to
finish before editing, or the two of you will overwrite each other's
edit.

It is refused in both directions: the studio will not start a turn while an MCP call is in flight either. Two editors on one timeline write conflicting EDL versions and each reads state the other is halfway through changing, so the loser is not a merge conflict — it is a silently wrong edit.

The fix is to let the turn finish, or work on a different project. The other direction is specific too: a studio request sent while an MCP call is in flight answers "Another editing session is working on this project right now — give it a moment", which is a different sentence from the one you get when the studio's own agent is busy. Neither side pretends the other does not exist.

Permissions for Unattended Runs

If you script this, Claude Code's permission rules are what stop each tool call stopping for a prompt. MCP rules use the server name as configured:

.claude/settings.json

{
  "permissions": {
    "allow": ["mcp__valmera__*"]
  }
}

mcp__valmera matches every tool from the server, mcp__valmera__* does the same with a wildcard, and mcp__valmera__cut_silences matches one. Allow globs must be anchored after a literal mcp__<server>__ prefix — an unanchored "*" or "mcp__*" is skipped with a warning and auto-approves nothing.

Worth being deliberate here rather than pasting the blanket rule. Reading the transcript costs nothing; rendering, generating a clip and erasing pixels are real compute and spend credits. An allow-all on a loop nobody is watching is a way to spend money without a decision. Allowing the read tools and prompting on render_preview is a reasonable middle.

What This Does Not Do

The connector is not a local toolchain and does not pretend to be one.

  • Nothing renders on your machine. The only thing that runs locally is the upload and the download. There is no local ffmpeg step to cache, parallelise or pin a version of.
  • Each version needs review. A 16:9 version and a 9:16 version need their own framing checks. Multiple child clip projects can be seeded with make_shorts, but each needs its own edit and preview. The user starts final exports in Studio; there is no automatic batch-export matrix over MCP.
  • Captions are burned in. No SRT or VTT is produced or accepted, so there is no subtitle file to commit alongside the MP4, and no chapter metadata.
  • It edits footage, it does not generate it. Short generated clips and stills can be spliced in, but there is no whole-video text-to-video. Upload something real.
  • No NLE interchange. No project file for Premiere, Resolve or Final Cut, no multi-cam sync, no true crossfade, and one transition style per video rather than per cut.
  • Uploads cap at 14 GB and 3 hours, in MP4, MOV, M4V, MKV or WebM. A five-hour raw capture is refused before the upload, not after it.
  • No team seats, share links or direct publishing. The user creates the final export in Studio, then downloads and posts that file.

Claude Code calls Valmera's tools directly and writes its own replies. Tool results and recorded edit state provide evidence to check, but Valmera does not guarantee the external assistant's summary. Inspect the preview and verify the requested cuts, captions and audio. For supported operations, use the tool reference; the common ones have their own pages, like silence removal, captions and reframing.

Frequently Asked Questions

Not on its own — Claude Code has no video engine and cannot render a file. Connected to a video editing MCP server it can. With Valmera added as a remote HTTP server, Claude Code gets 100+ live tools (100+ editing, 12 session) and can create a project, upload a local file, cut silences and filler words, add captions, reframe to 9:16, render a preview, inspect it, and download that review render to a path in your repo. The source-quality final is deliberately created by the user in Valmera Studio.
Run: claude mcp add --transport http valmera https://entrepreneur-bot-backend.onrender.com/mcp. Then start Claude Code, run /mcp, and complete the browser sign-in. Claude Code discovers the authorization server from the endpoint, registers itself dynamically, and stores the token in your keychain. Confirm with claude mcp list, which shows a health status next to each server.
Point an MCP client that has a shell at an editing engine that has an API. Claude Code is that client; Valmera is that engine. The pairing works because upload_start hands back a presigned URL and the exact curl command to push the bytes — a chat app cannot run that command, and a terminal agent can. Ask it to cut, caption, reframe, render and download the review preview. When the edit is approved, open the project in Valmera Studio for the source-quality final export.
Local (the default) stores the server in ~/.claude.json under the current project's path — private to you, this repo only. Project writes .mcp.json in the repo root, which you commit, so every teammate gets it. User stores it in ~/.claude.json for all your repos, still private to you. When the same name appears in more than one, local wins, then project, then user; the whole entry from the winning source is used and fields are not merged.
claude mcp add --transport http valmera --scope project https://entrepreneur-bot-backend.onrender.com/mcp writes .mcp.json at the repo root. Commit it. The file carries the URL and the transport type, never a credential — each teammate authenticates as themselves with /mcp, against their own Valmera account and their own credits. Claude Code prompts each of them for approval before it will use a server defined in .mcp.json; claude mcp reset-project-choices clears that answer if someone needs to redecide.
Yes. claude mcp add --transport http valmera https://entrepreneur-bot-backend.onrender.com/mcp --header "Authorization: Bearer vlm_mcp_..." attaches a static token, which is what a client with no OAuth support or a headless environment needs. Tokens are shown once and stored only as a sha256 hash, so a lost token is replaced rather than recovered. In a committed .mcp.json, reference it as ${VALMERA_MCP_TOKEN} — Claude Code expands environment variables inside headers, so the secret stays out of git.
Because it has not finished, and saying so is better than blocking or lying. Preview renders and pixel repainting outlast any sensible request timeout, so they return a job id: "STILL RUNNING — render_preview is job 8814 (running, 12%). Nothing has failed; call wait_for_job(job_id=8814) to pick the result up." Every Valmera call returns inside about 25 seconds, which keeps it under Claude Code's 60-second per-request timer for HTTP servers. Final export is a Studio-only user action, not an MCP job.
Mechanically yes, and there are three things to get right. Authenticate with a bearer token — a claude -p or Agent SDK run has no /mcp panel, so Claude Code cannot run the OAuth flow for you, and claude mcp login --no-browser is not the way round it: that path still needs an interactive terminal for the paste step, which makes it an SSH answer rather than a CI one. Allow the tools you need in permissions (mcp__valmera__* matches every tool from the server; an allow glob must be anchored after the mcp__<server>__ prefix). And know that non-interactive runs do not background long tool calls unless CLAUDE_AUTO_BACKGROUND_TASKS is set to 1, so the wait_for_job loop is your own responsibility. The honest caveat is editorial, not technical: an unattended run has nobody to judge the preview. The agent checks its own frames, but that is a correctness check, not your taste.
Yes, and that is the main thing it has over the Claude app. upload_start returns a presigned URL plus the literal curl command to run, and Claude Code runs it with Bash. Files up to 16MB go as one PUT; above that the upload is multipart, so upload_start returns a part size and one presigned URL per part, and the agent PUTs each part and passes the ETags back to upload_finish. You can also skip the local file entirely and give it a link to fetch.
No, and it is refused in both directions rather than allowed to corrupt the edit. An MCP tool call on a project with a studio agent turn in flight answers: "Valmera's own agent is mid-turn on this project — wait for it to finish before editing, or the two of you will overwrite each other's edit." The studio refuses to start a turn while an MCP call is running. Two writers on one edit decision list each read state the other is halfway through changing.
It is a standard streamable-HTTP MCP server with OAuth 2.1, dynamic client registration and PKCE, plus a bearer-token path for clients that do not implement OAuth. Any compliant client should work. Claude Code and the Claude app are the two we have verified end to end, and we would rather name those two than list clients we have not tested.
You need a verified Valmera account with an active Pro or Frontier subscription. MCP access is included automatically for Pro and Frontier subscribers. Account creation and uploads are available without charge, but agent editing requires a subscription. Current terms and included credits are on the live Plans page. Your external assistant’s own model usage is billed by that provider.

Add It to Your Next Session

Create a free Valmera account, run one claude mcp add, sign in with /mcp — then edit your next screen recording without leaving the terminal.

Create a free account →
See pricing →

Related Articles

Connect Claude to Video Editing
The same server from the Claude app's connector UI — one paste, one sign-in, no commands.
Valmera MCP Server
The server itself: transport, auth, and the design decisions behind it.
MCP Tool Reference
The complete live name list, grouped by job, plus core capability and refusal notes.
Video Editing MCP Servers
Every MCP server that edits video, compared — including where another one is the better answer.
Agentic Video Editor
Why an editor built as an agent is the kind another agent can drive.