
Chat raw clips into a finished cut.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent — or use 1-click editor setup below.
💡 Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
Inspect callable tools, capabilities, and parameters exposed to AI agents by Oh My Cassette.
cassette_ingest_mediaSafely ingest trusted project media into an isolated session
cassette_list_assetsRead the session's media manifest
cassette_make_prompt(legacy) Build a full edit brief — superseded by verbatim relay
cassette_match_bgmMatch Free To Use background music
cassette_match_exact_bgmMatch a specific title and artist
jamendo_music_matcherMatch structured Jamendo preferences
简体中文 | English
14 clips in. One prompt. ~13 minutes to a rendered file.
No timeline. No editing software. No GPU.
Restart your agent, then say: "Edit the clips in ./footage into a 30-second travel vlog with beat-synced cuts."
Needs Python 3.11–3.13, ffmpeg, and a Cassette account. Full setup — including OpenCode, Hermes, and any other MCP host — is in Quick Start. Want to try it first? Run it in your browser — no install, no account.
Oh My Cassette is an open-source AI video editing plugin and local MCP server for Claude Code, Codex, Hermes Agent, and OpenCode. It turns natural-language chat into finished montage videos on Cassette — beat-synced cuts, auto-matched music, subtitles, transitions, and picture-in-picture — with minimal token overhead.
The agent does the parts that make editing tedious: it watches every clip, picks the shots, plans the cut, syncs it to the beat, and renders — while you stay in chat. Because it runs through your agent, you can do all of it from your phone.
💬 Chat-to-EditDescribe the video in plain language — the agent handles shot selection, pacing, and the timeline, so you never open an editor. |
🎵 Smart Music MatchingFinds and syncs music to the mood and rhythm of your footage, so the cut lands on the beat without you marking a single one. |
👀 Nothing Renders Until You Say SoEvery turn returns a timeline digest and a contact sheet you can review in seconds — you approve the plan before a frame is rendered. |
Upload your clips, describe the video you want, and the agent edits it.
| Time | What happens |
|---|---|
| 0:09 | The brief — one line, style left entirely to the agent, typed into Claude Code |
| 0:22 | 15 files upload to Cassette; every clip is analyzed for scene content |
| 0:35 | The agent edits on its own — shot selection, title card, lower-third, grading, beat-synced cuts |
| 0:58 | The timeline comes back as a readable digest, with a clickable contact-sheet link |
| 1:03 | One cmd+click opens the real contact sheet — one frame per clip, zero render |
| 1:12 | The contact sheet itself: what the cut looks like before a single frame is rendered |
| 1:44 | The export lands, and the runtime measures it — duration, black frames, audio levels |
| 1:52 | The finished cut |
The cut it produced
The screen recording is compressed to keep this page light, so the terminal text looks softer here than it does on your machine; the cut below it is the full-quality render. Prompt to rendered file took 9 minutes 53 seconds of real time, sped up above. A person's face is pixelated in both the screen recording and the cut it produced, for privacy — that blur is not something the agent added.
Token cost: that session used 55K output tokens and 2.33M billed input tokens (2.07M of them cache reads) on Claude Opus 5 — roughly $4 at API list price, measured from the Claude Code transcript of this exact recording. One brief, one turn, start to exported file. The editing itself runs on Cassette, so the agent only pays for the brief and the timeline digests, not for the footage.
Every case below was edited end-to-end by an AI agent through Oh My Cassette, from the exact prompt shown — real inputs, real processing times, and the output is what the agent delivered.
Travel Vlog
🎞️ Input: 13 video clips · 1 audio track Prompt
|
Cooking Tutorial
🎞️ Input: 12 video clips · 1 audio track Prompt
|
Commercial
🎞️ Input: 15 video clips · 15 sound effects · 1 audio track Prompt
|
→ See all six cases — daily vlog, cinematic short, and game highlights, each with its exact prompt.
★ More cases are on the way. Star the project to follow along.
Upload a clip, type an edit, watch it happen — from a desktop or mobile browser, with no agent installed locally.
[!WARNING] Evaluation demo — unauthenticated and public. Don't upload anything sensitive, private, or copyrighted.
The demo is a separate deployment with its own repository and its own transport; this repository is the plugin only.
Oh My Cassette connects Codex, Claude, or Hermes to the Cassette Agent. You need:
[!TIP] Apply for a Cassette account here: Cassette Sign Up
If you plan to use Hermes and it is not installed yet:
If the Hermes Agent gateway is not configured yet:
Oh My Cassette currently supports QQ and Telegram gateways.
ffmpeg, required for Hermes gateway normalization and optional API export thumbnails.Install system tools:
Start a new Codex task after installation so plugin discovery runs again. The plugin contributes the host-neutral cassette-video-edit and cassette-model skills plus a local MCP process named cassette. Fresh editing sessions use GPT-5.6 Luna with Extra High thinking; invoke $cassette-model only when you want to inspect or change that session setting.
Restart Claude Code after installation. You can verify the installation with:
Claude Code can keep the plugin up to date on its own once you enable auto-update for the marketplace — see Update.
Fresh editing sessions use GPT-5.6 Luna with Extra High thinking. Invoke /cassette-model when you want to inspect or change the current session's model and thinking level.
OpenCode's plugin manager installs npm packages only, and its plugins cannot contribute MCP servers, so there is no marketplace entry to add. One command instead:
That downloads the current release, writes the cassette server into ~/.config/opencode/opencode.json (merging with any servers and settings already there), installs the host-neutral skills into ~/.config/opencode/skills/, and installs /cassette-model into ~/.config/opencode/commands/. Restart OpenCode afterwards. Fresh editing sessions use GPT-5.6 Luna with Extra High thinking; the command changes the setting only when you invoke it.
Re-run the same command to update. Only git is not required — the release tarball is fetched with Python's standard library.
Cassette credentials are shared across Codex, Claude Code, OpenCode, and Hermes, so if you have already set up another host there is nothing more to do. Otherwise the installer prints the setup_local_mcp.py command to finish authentication. Jamendo uses the host-specific BYOK setup described below.
The plugin tree lands in ~/.oh-my-cassette (override with OMC_HOME). --dry-run previews the changes. If you prefer a git checkout, clone it and run the installer from there — it registers that tree and leaves it alone, and --sync fast-forwards it to the release channel.
The runtime is host-neutral, so any client that launches a local stdio MCP server can use it. Point the client at scripts/run_local_mcp.py (run with python3, or python on Windows) and set CASSETTE_RUNTIME_ADAPTER=mcp. The server ships full workflow guidance in its MCP instructions, and every tool returns a typed phase/next_action so a host without the packaged skill can still drive the flow. For the best experience, also install the cassette-video-edit and cassette-model skills (or equivalent system prompts). Generic clients can call cassette_config or ask in natural language to change the current session's model.
Install through the Hermes plugin manager (recommended):
The Hermes installer prompts for your Cassette account email and password and saves them to ~/.hermes/.env. Then run the setup finisher — it configures the same stdio MCP server and canonical editing skill used by the other hosts, sets Hermes's tool timeout to 1800 seconds, detects ffmpeg/ffprobe, and lets you pick the Cassette region — and enable the thin gateway plugin:
You can check the install status anytime from the Diagnose section.
Run the installer and follow the prompts to set up Oh My Cassette with your Cassette account.
The installer:
~/.hermes/plugins/cassette as a symlink by default;~/.hermes/config.yaml with an 1800-second tool timeout;hermes plugins enable cassette;https://sg.trycassette.online/agent (Asia, default)https://trycassette.online/agent (America)~/.hermes/.env;ffmpeg and ffprobe paths for service environments;To copy files instead of creating a symlink:
For non-interactive installs:
Codex, Claude Code, OpenCode, and Hermes use the same self-contained runtime. In this README, MCP server means a local child process connected over stdin/stdout: it opens no port and does not depend on the FastAPI web-demo service. The separate Cassette backend remains the editing engine and continues to handle authentication, media processing, agent runs, project state, and rendering.
The web demo is intentionally different. Browsers still need the retained FastAPI server for uploads, chat sessions, and frontend endpoints; none of that behavior is removed by the local MCP plugin.
Cassette passwords are generated by the server and emailed to you. You never choose one, and the plugin never invents one.
Missing credentials do not prevent the MCP process from starting. There are two ways to hand the password over.
In the conversation. Paste the password from your Cassette email and ask the agent to sign in; it calls the cassette_login tool, which verifies the account against Cassette before writing anything and then stores it privately. Nothing else is needed — no terminal, no browser. The trade-off is explicit: the password lands in your agent host's transcript on disk and is sent to the model provider for the rest of that conversation. If that is not acceptable to you, use the terminal instead.
In a private terminal. The command keeps the password out of the transcript entirely — it prompts with getpass, verifies the account before writing anything, and stores credentials in the platform-standard Oh My Cassette config directory. Every auth_required envelope carries the exact command for your install; from a git checkout it is:
Credentials may also come from process environment variables. Environment values take precedence over protected local config, so cassette_login refuses to write a file that would be shadowed. Importing an existing Hermes .env is explicit and optional:
Either route creates config directories with mode 0700 and credential files with mode 0600, rejects symlinks and permissive files, and never persists access or refresh tokens.
Jamendo music matching is strictly bring-your-own-key for every local agent host. Create a read-only application in the Jamendo developer portal and copy its Client ID. A Client Secret is neither needed nor accepted.
In the conversation. Ask the agent to configure Jamendo, paste your Client ID, and it calls cassette_jamendo_setup. The tool verifies a minimal Tracks request before writing anything. The trade-off is the same as chat sign-in: the ID reaches the host transcript and model provider for that conversation.
In a private terminal. Keep the ID out of the conversation entirely:
Codex, Claude Code, and OpenCode store it in the protected settings.json; Hermes stores it in ~/.hermes/.env. JAMENDO_CLIENT_ID in the process environment remains highest precedence. A failed validation preserves the previous working value.
BYOK assigns API access and quota to your Jamendo application; it does not grant commercial rights to selected music. Review the returned track URL, license URL, download eligibility, and attribution requirements before publishing or commercial use.
You cannot pick a replacement — Cassette generates one and emails it to the account address. Ask the agent for a new password and it calls cassette_login with request_new_password and confirm_replace; or from a terminal:
Both routes ask you to confirm first, because the request is irreversible: it replaces the account password everywhere, including on your other machines, it is limited to a few attempts an hour, and the replacement happens before the email is sent — so even a delivery failure kills the old password. Check your inbox before retrying.
The reset only mails the new password; paste it back (in the conversation, or at the terminal prompt) to finish signing this machine in. The verified password is stored in credentials.json:
~/Library/Application Support/Oh My Cassette/credentials.json~/.config/oh-my-cassette/credentials.json (or under XDG_CONFIG_HOME when set)%APPDATA%\Oh My Cassette\credentials.jsonTo make this machine forget the stored password without touching the account:
Start your agent in the folder that holds the clips — or in any parent of it. That folder is the trusted media root (CASSETTE_PROJECT_ROOT, set to the host's project directory), and everything beneath it is ingestible, so ~/videos/trip/raw/*.mp4 works when you start in ~/videos/trip. Clips somewhere else? Register that directory once:
Ingesting a file outside every trusted root fails with source_path_not_allowed.
Say what you want, in one message, naming the folder. No upload step to run yourself — the agent ingests the files it needs.
Edit the clips in ./footage into a 30-second travel vlog with beat-synced cuts. Add the title "KOTA KINABALU" at the start and end, and keep the rhythm light.
Keep going in the same conversation. Each turn commits the edit and returns a timeline digest plus a contact-sheet JPEG saved locally with a clickable link — nothing renders. Hermes labels this as the thumbnail and uses the same saved file; no editor deep link is exposed. "Make the intro shorter", "swap the music for something calmer", and "undo that" all continue the same session.
Say "export" when you're happy. That's the only thing that starts a render; the finished file lands in cassette/exports/<job_id>/.
Supported inputs are video, image, and audio files (.mp4, .mov, .jpg, .png, .mp3, .wav, and friends). Mixed folders are fine — send the footage and the music track together.
What the plugin does under the hood on each of those turns:
cassette_run_job is the wait: the host calls it exactly once for that user turn while the runtime streams progress notifications.phase and next_action; do not start a status-poll loop or retry the edit in the same user turn. cassette_job_status is reserved for a deliberately detached or interrupted call.cassette_job_status collects the answer inline and returns the already-resumed status; other hosts use the cassette_answer_question round-trip. API jobs persist their private continuation metadata across host restarts.export decision.When a background job reaches a terminal state (finished, needs input, failed, or cancelled), the MCP runtime posts a best-effort local desktop notification — osascript on macOS, notify-send on Linux — so you learn a long render is done even after the monitor budget hands the job back. Set CASSETTE_MCP_NOTIFY=0 to disable it.
Sessions are isolated by a cryptographically random session ID. Codex, Claude Code, OpenCode, and Hermes share host-neutral storage, so you can deliberately hand a session or job ID from one host to another; nothing is shared implicitly.
Additional trusted media directories can be registered during setup:
Exports stay under the shared Oh My Cassette data directory at cassette/exports/<job_id>/. Only files contained in that job-specific directory can be returned.
One way: direct calls to the separate Cassette backend. Authentication retries once after a 401, access tokens are kept in memory only, and continuation metadata is persisted, so a paused job resumes after the agent client restarts.
There is no browser to install, drive, or keep alive. The Playwright transport that used to sit behind CASSETTE_TRANSPORT=browser has been removed; a leftover setting is reported once on stderr and ignored.
The local MCP runtime exposes the same 16 tool names as Hermes:
| Tool | Purpose |
|---|---|
cassette_ingest_media | Safely ingest trusted project media into an isolated session |
cassette_list_assets | Read the session's media manifest |
cassette_make_prompt | (legacy) Build a full edit brief — superseded by verbatim relay |
cassette_match_bgm | Match Free To Use background music |
cassette_match_exact_bgm | Match a specific title and artist |
jamendo_music_matcher | Match structured Jamendo preferences |
cassette_jamendo_setup | Verify and privately store this machine's Jamendo Client ID |
cassette_answer_question | Answer a guided question or resume a paused job |
cassette_run_job | Run one conversational turn (message = the user's verbatim words); export=true renders |
cassette_job_status | Resume a deliberately detached or interrupted job call |
cassette_review_completion | Review completion and explicitly approve export |
cassette_cancel_job | Request cooperative cancellation |
cassette_timeline | Read the live project timeline as a bounded text digest (+ optional contact sheet) |
cassette_edit | Surgical no-LLM edit / undo through the manual command lane (CASSETTE_DIRECT_EDIT=1) |
cassette_config | Get/set the session's model + thinking level (static product list, applies next turn) |
cassette_login | Verify and privately store this machine's credentials, or request a new emailed password (MCP hosts only) |
Every tool returns a structured envelope with ok, typed data or error, session_id, job_id, the current phase, and a runtime-derived next_action.
The runtime returns no editor deep link. A …?projectSessionId=<id>&chatSessionId=<uuid> URL is a bearer capability: the backend binds no owner to a scratch session, so the only checks on that route are "signed in" and "knows the id" — any authenticated account that sees the link can open the project and run edits on the thread. Tool output ends up in chat transcripts, logs and screen recordings, so the runtime no longer emits one, and the skills instruct the agent not to construct one. Previews are the timeline digest, the contact sheet, and the export.
This narrows exposure rather than closing it: the route still resolves for anyone who reconstructs the URL. Binding a session to its owner has to happen server-side.
Two concurrency semantics worth knowing: a plugin turn never cancels a run started from the open editor tab (it fails typed as thread_busy instead — wait and retry), while typing a fresh message in the tab DOES cancel an in-flight plugin turn (the tab takes over; existing product behavior).
Behavior change (0.4.14): the agent receives the user's message verbatim (no brief wrapper), sessions are multi-turn on one thread, and a turn ends with the edit committed but nothing rendered — the envelope carries timeline_delta, quality.timeline_ctl, and a contact-sheet preview instead; pass export=true on the turn where the user asks to finish. A fresh session starts immediately with GPT-5.6 Luna and Extra High thinking; model selection is opt-in through $cassette-model in Codex, /cassette-model in Claude Code/OpenCode, /cassette_model in Hermes, or an explicit natural-language request. The saved session preference applies from the next turn.
Behavior change (0.4.0): on MCP hosts, edit_plan_review now surfaces as a real question by default (CASSETTE_PLAN_REVIEW=user) instead of being silently auto-approved — answer with approve, revise <feedback>, or reject, in chat or in the open editor tab (first answer wins). Set CASSETTE_UNATTENDED=1 to restore the previous fully headless behavior. Status envelopes additionally carry timeline_delta (what changed) and plan_progress, fed by the run's SSE event stream (CASSETTE_API_STREAM=0 disables).
Now you can pick up your phone and DM your agent! Don't forget to keep your agent alive and network connected.
In QQ or Telegram:
/edit. The session starts with GPT-5.6 Luna and Extra High thinking; send /cassette_model only when you want to change them. Your words go to the Cassette agent verbatim; optimization and BGM remain explicit via /refine and /music.| Command | Explanation |
|---|---|
/new or /reset | Clear your assets and start a new conversation with Hermes |
/edit <instruction> | Edit the current video based on your instruction. |
/refine <instruction> | Refine your edit instruction and start editing. |
/music <BGM request> | Match and add a BGM to your assets based on your request. |
/cut | Stop the current Cassette edit. |
/check_assets | Check the uploaded assets and their status. |
/cassette_model | Select the current Cassette model and thinking level. |
/cassette language zh | Set Cassette’s response language to Chinese. |
/cassette language en | Set Cassette’s response language to English. |
/cassette status <job_id> | Check the status of a specific job. |
/cassette cancel <job_id> | Cancel a specific job. |
Assets and video state are preserved within the same conversation session. You can send additional messages in the same session to further modify the edited video results.
Use /new or /reset to start a fresh Hermes session and clear the live Cassette session and your assets for that conversation.
QQ is set to Chinese and Telegram is set to English by default, you can set language by command /cassette language zh/en manually.
The runtime checks the release channel once a day and, when a newer version exists, tells your agent — which mentions it once and offers to run the command below for you. Set CASSETTE_UPDATE_CHECK=0 to turn that check off.
| Host | Automatic | Manual |
|---|---|---|
| Claude Code | yes, once enabled (below) | claude plugin marketplace update cassette-editor && claude plugin update oh-my-cassette@cassette-editor |
| Codex | marketplace snapshot only | codex plugin add oh-my-cassette@cassette-editor |
| Hermes | no | hermes plugins update cassette && hermes gateway restart |
| OpenCode | no | re-run the install command |
Claude Code checks for marketplace and plugin updates after your session starts, with a random delay of up to ten minutes, so the session you are in keeps the version it launched with — you are prompted to run /reload-plugins, or the new version loads next launch. It is off by default for third-party marketplaces, so turn it on once — scripts/setup_local_mcp.py offers to do this during setup (skip with --no-auto-update), or do it yourself in /plugin → Marketplaces → cassette-editor → Enable auto-update, or in ~/.claude/settings.json:
Declaring it in settings.json wins over the /plugin toggle — Claude Code syncs the declared value into its marketplace state and then points you back at the settings file to change it.
Because the setup prompt only runs at setup, an install that predates it — or one where it was declined — would never hear about the toggle again. So on Claude Code the runtime also reads that setting at startup and, while auto-update is off, asks your agent to mention it at most once per session and point you at the toggle. Your agent will not edit your Claude configuration itself. CASSETTE_UPDATE_CHECK=0 silences this along with the release check.
Claude Code's DISABLE_AUTOUPDATER turns off all automatic updates including plugins; pair it with FORCE_AUTOUPDATE_PLUGINS=1 to keep plugin updates while managing Claude Code itself manually.
Codex refreshes configured git marketplace snapshots on its own, but installed plugins are cached per version, so one command applies the new one:
Re-run the install command — it is the same command for installs and updates:
The local launcher updates its locked, plugin-managed virtual environment automatically on the next start after any of these.
If installed through the Hermes plugin manager:
If installed from a git checkout (symlink install), update the checkout:
If the plugin was installed with --copy, reinstall the copied plugin after pulling:
See CHANGELOG.md for what changed in each release.
Existing symlink installs keep working — migration is optional. To switch:
Your credentials in ~/.hermes/.env and the plugin's enabled state carry over;
already-set values are not prompted again. Don't run
hermes plugins install --force on top of a symlink — it fails with a
confusing error instead of replacing it.
Claude Code, Codex, OpenCode, and Hermes Agent are supported out of the box, and any other MCP host can connect to the local cassette MCP server. Sessions live in a host-agnostic data directory, so you can start an edit in one host and continue it in another.
The plugin runs locally beside your agent and handles media ingestion, edit planning, and job supervision. The actual editing and rendering happen on Cassette, so you don't need a GPU or any editing software installed.
Yes. The installer asks for your Cassette account email and password on first run and stores them locally; the plugin authenticates with Cassette on your behalf.
Montage and story edits — vlogs, travel videos, music-driven shorts, cooking tutorials, product commercials, and game highlights — with beat-synced cuts, subtitles, picture-in-picture, transitions, and auto-matched background music. See Case Videos for real examples with prompts and processing times.
Yes. After each editing turn you get a timeline digest and a contact-sheet JPEG saved locally. Terminal clients present a clickable local thumbnail link, and supported gateway clients can deliver the preview as an image. Before the edit runs, the agent can also surface the plan as a storyboard sheet (one source frame per planned beat) for review. The plugin intentionally does not expose an editor deep link.
Yes — the public web demo runs the full workflow in your browser. It is unauthenticated and for evaluation only, so don't upload sensitive content.
This plugin is free and open source under the MIT license — all of it, including the MCP server and the skill.
Rendering runs on Cassette, a separate hosted service that requires an account. See Cassette's pricing for what an account costs. You can try the whole workflow with no account at all through the web demo.
Setup for contributors, the full configuration reference, transport internals, the diagnostic scripts, and answers to common runtime problems all live in docs/development.md.
Quick diagnostic — run this first when something misbehaves:
Both report bootstrap, config, transport, and media-root state without printing credentials.
good first issue are a good place to start.Made something you like with it? Post it in Discussions — we feature the best cuts in the showcase.
MIT. See LICENSE.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/cassette-editor-oh-my-cassette)<a href="https://allmcps.com/mcp/cassette-editor-oh-my-cassette"><img src="https://allmcps.com/api/badge/cassette-editor-oh-my-cassette?style=directory" alt="Oh My Cassette on AllMCPs" /></a>