Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Turn long videos into short, captioned viral clips from your agent via the OpenClip MCP server. Also FREE with just an account (no subscription): transcribe a video, convert/compress/trim/crop/resize/mute a video, extract thumbnails, edit an image, remove an image background. Plus generate a short UGC-style ad clip from a brief. Triggers include "clip this video", "make shorts", "repurpose this", "find viral moments", "transcribe this", "convert to mp4/gif/mp3", "compress this video", "remove th
.claude/skills/oak-ridge-ventures-openclip/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 105% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 146% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 287% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 99% | 0% |
OpenClip is a video editing MCP server. Its headline pipeline turns a long video into short, captioned, ranked clips, and around that it exposes 28 tools in five groups, identical in every client:
submit_video, get_video_status, list_clips, render_clip,get_render_status, list_caption_presets, get_transcript, list_supported_providers, list_videos.
create_upload, complete_upload (see the gotcha below: complete_uploadstarts the PAID pipeline; free tools skip it).
transcribe, edit_video,convert_media, extract_thumbnails, edit_image, remove_background, get_tool_job_status.
generate_ugc, get_ugc_job_status.get_account, get_usage, list_agents, create_agent,update_agent, describe_agent_settings, create_agent_logo_upload, set_agent_logo.
The remote server supports OAuth one-click as the primary path: paste the server URL (https://openclip.app/mcp) into your client and sign in with your OpenClip account, no token to copy.
https://openclip.app/mcp):https://openclip.app/mcp → Connect → sign in.
claude mcp add --transport http openclip https://openclip.app/mcp,then run /mcp and authorize in the browser.
.cursor/mcp.json):{ "mcpServers": { "openclip": { "url": "https://openclip.app/mcp" } } }, Cursor runs OAuth.
MCP token at openclip.app/settings/connect ("Generate MCP token", shown once) and connect to the /mcp/key endpoint with it as a Bearer header:
claude mcp add --transport http openclip https://openclip.app/mcp/key --header "Authorization: Bearer <token>"
.cursor/mcp.json):{ "mcpServers": { "openclip": { "url": "https://openclip.app/mcp/key", "headers": { "Authorization": "Bearer <token>" } } } }
https://openclip.app/mcp/key with header Authorization: Bearer <token>.get_account. Confirm credits_remaining > 0.(Self-hosting/dev only: run the local stdio server with php artisan mcp:start openclip.)
submit_video(url) → returns a job_id with status:"queued". This ALWAYSsucceeds (queues the job) when authenticated, it does NOT pre-check subscription or credits.
get_video_status(job_id) until status is completed (or failed).Do NOT call list_clips before completion. Read status for the real state:
failed (often almost immediately after submit) usually means no active subscription -advise the user to subscribe at openclip.app.
pending_credits means the team is out of credits, advise the user to top up.download_failed means the source URL couldn't be fetched, ask the user to check the link.list_clips(job_id) → viral moments with virality_score (0-10),title/hook, start/end (ms), and clip / rendered_clip URLs.
render_clip(moment_id, caption_preset). Async too, polllist_clips and watch the moment's rendered_clip for the finished URL. Preset keys: list_caption_presets.
transcribe, edit_video, convert_media, extract_thumbnails, edit_image, and remove_background are FREE: they only need an account, not a subscription or credits. All follow the same async pattern:
create_upload(filename, content_type), PUT thebytes to the returned upload_url, and use the returned id as file/video. Do NOT call complete_upload for free tools - that starts the paid clipping pipeline; free tools read the uploaded file directly. (Videos already in list_videos work as inputs too.)
tool_job hashid with status: "queued".get_tool_job_status(tool_job) every 5-10s: queued/processing are in-flight,completed/failed terminal. On completed it returns permanent CDN outputs URLs (e.g. json/srt/vtt for transcribe, a zip of frames for extract_thumbnails). On failed it returns error.
Operation cheat sheet (full params in reference.md): edit_video does one operation of crop, trim, rotate, resize, compress, or mute; convert_media targets mp4/webm/mov/mkv, gif, or mp3/aac/wav/flac; edit_image does compress, resize, or crop; remove_background returns a transparent PNG. Free usage is rate-limited per day with per-file size caps; the error text explains how to lift a limit.
Note the transcript split: transcribe is the free tool for uploaded files; get_transcript reads the time-coded transcript of a video that went through the paid clipping pipeline (supports start_ms/end_ms windows at sentence or word level).
generate_ugc renders a short (~7-12s) vertical UGC-style clip from a creative brief (NOT a prose prompt: structured fields like character, or a server-side brief_name preset). Free accounts get ONE generation per day; paid accounts are metered in credits by the seconds rendered. It returns a ugc_job hashid; poll get_ugc_job_status every 10-15s (queued/rendering in-flight, completed returns video_url + result_meta, failed returns error). Renders are heavy: expect a couple of minutes.
To make repeat workflows identical (same tracker model, caption preset, composition, logo watermark), save a processing agent once with create_agent and pass it to submit_video. describe_agent_settings documents every nested field and allowed value; update_agent patches only the fields you send; create_agent_logo_upload + set_agent_logo attach a watermark (max 2 MB). get_usage reports the credit balance (credits are MINUTES of processing) and recent activity.
get_video_status in a loop.virality_score (higher = better) unless the user says otherwise.clip.url is a permanent CDN URL (not signed/expiring).submit_video queues regardless of subscription/credit state; the gate surfaces LATER inget_video_status (failed = no subscription, pending_credits = out of credits). Read the status and advise the user accordingly, do NOT expect a synchronous "subscribe" error.
These are MCP tools, not a REST/HTTP API. A failed tool call returns a normal tool result with isError: true and a short plain-text message (no HTTP 401/402/403/422 status, no JSON error envelope). Read the message text and act on it:
"Not authenticated. Reconnect your OpenClip token.", the connection isn't carrying avalid identity → reconnect. For the OAuth path, re-run the connector sign-in (e.g. /mcp in Claude Code); for the manual /mcp/key path, re-generate the MCP token on the connect page and re-add the server with the new Bearer token. (A token missing the mcp:use scope/ability is rejected at the transport before any tool runs, same fix: reconnect / re-mint.)
"Job not found." (get_video_status, list_clips), the job_id is wrong, from adifferent account, or expired → re-check the id you passed; if it was from an earlier session, re-submit the video.
"Viral moment not found." (render_clip), the moment_id is wrong or belongs toanother account → re-fetch moments with list_clips and use an id from that response.
"Video not yet available. Check get_video_status for progress." (list_clips), the jobhasn't produced a video record yet (still queued/downloading) → keep polling get_video_status and only call list_clips once status is completed.
url, an unknown caption_preset), thevalidation error text is returned as the tool message → fix the offending argument and retry.
get_video_status statusvalues (failed = no subscription → subscribe; pending_credits = out of credits → top up), not as a tool error. See "The loop" above.
submit_video(url), poll get_video_status, then list_clips.list_clips, sort by virality_score, take 3.render_clip(m_…, caption_preset="beast"), poll.create_upload, PUT bytes, transcribe(video), pollget_tool_job_status (NO complete_upload).
create_upload, PUT bytes,convert_media(file, to="gif") / edit_video(file, operation="compress"), poll.
create_upload, PUT bytes,remove_background(file), poll, return the transparent PNG.
generate_ugc(brief={...}), poll get_ugc_job_status.See reference.md for status values, preset keys, operation params, and field shapes.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | fail→pass | 10,169 | 4,804 | -53% | 1 | 1 | 0% | 1,795 | 3,678 | +105% | 0 | 0 | — |
case-01 | fail→fail | 7,438 | 4,185 | -44% | 1 | 1 | 0% | 1,263 | 3,056 | +142% | 0 | 0 | — |
case-02 | fail→fail | 3,918 | 6,591 | +68% | 1 | 1 | 0% | 667 | 3,255 | +388% | 0 | 0 | — |
case-12 | fail→pass | 6,551 | 2,305 | -65% | 1 | 1 | 0% | 1,306 | 3,212 | +146% | 0 | 0 | — |
case-03 | fail→fail | 8,267 | 6,895 | -17% | 1 | 1 | 0% | 1,409 | 3,301 | +134% | 0 | 0 | — |
case-04 | pass→pass | 6,489 | 3,317 | -49% | 1 | 1 | 0% | 1,161 | 3,361 | +189% | 0 | 0 | — |
case-05 | fail→pass | 9,727 | 3,893 | -60% | 1 | 1 | 0% | 1,933 | 3,590 | +86% | 0 | 0 | — |
case-06 | fail→pass | 4,950 | 3,128 | -37% | 1 | 1 | 0% | 868 | 3,356 | +287% | 0 | 0 | — |
case-08 | pass→pass | 7,842 | 3,090 | -61% | 1 | 1 | 0% | 1,404 | 3,296 | +135% | 0 | 0 | — |
case-09 | pass→pass | 9,621 | 2,647 | -72% | 1 | 1 | 0% | 1,764 | 3,224 | +83% | 0 | 0 | — |
case-10 | pass→fail | 8,465 | 3,490 | -59% | 1 | 1 | 0% | 1,554 | 3,441 | +121% | 0 | 0 | — |
case-11 | fail→pass | 9,811 | 2,782 | -72% | 1 | 1 | 0% | 1,711 | 3,404 | +99% | 0 | 0 | — |
case-13 | fail→pass | 9,417 | 4,417 | -53% | 1 | 1 | 0% | 1,852 | 3,725 | +101% | 0 | 0 | — |
case-14 | fail→pass | 9,754 | 2,227 | -77% | 1 | 1 | 0% | 2,007 | 3,133 | +56% | 0 | 0 | — |
case-15 | fail→pass | 7,689 | 3,830 | -50% | 1 | 1 | 0% | 1,612 | 3,679 | +128% | 0 | 0 | — |
case-16 | pass→pass | 9,782 | 2,606 | -73% | 1 | 1 | 0% | 1,879 | 3,301 | +76% | 0 | 0 | — |
case-17 | fail→pass | 10,276 | 4,351 | -58% | 1 | 1 | 0% | 1,872 | 3,667 | +96% | 0 | 0 | — |
case-22 | fail→pass | 18,285 | 5,155 | -72% | 1 | 1 | 0% | 3,418 | 3,698 | +8% | 0 | 0 | — |
case-18 | fail→pass | 7,127 | 3,690 | -48% | 1 | 1 | 0% | 1,320 | 3,562 | +170% | 0 | 0 | — |
case-19 | fail→pass | 4,355 | 1,872 | -57% | 1 | 1 | 0% | 755 | 3,064 | +306% | 0 | 0 | — |
case-20 | fail→pass | 9,913 | 1,477 | -85% | 1 | 1 | 0% | 1,810 | 2,991 | +65% | 0 | 0 | — |
case-21 | pass→pass | 8,433 | 3,429 | -59% | 1 | 1 | 0% | 1,711 | 3,379 | +97% | 0 | 0 | — |
case-23 | fail→pass | 13,750 | 3,823 | -72% | 1 | 1 | 0% | 2,534 | 3,471 | +37% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 20 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +57 percentage points is the difference between those two pass rates over the 20 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.