MCP for Video Editing and Clipping Workflows

Ask a video MCP server to clip something and it will not hand you a video. It hands you a string. For a recorded source that string is a projectId; for a live stream it is a subscriptionId. Nearly every design decision on this page falls out of that one fact — the protocol carries small JSON, the media does not travel through it, and the agent's job is to hold an identifier and come back later.

That makes video an unusual thing to expose over the Model Context Protocol. Most MCP tutorials demonstrate tools that return in milliseconds: read a file, query a row, look up a ticket. Transcribing an hour-long podcast, scoring its moments, reframing each one to 9:16 and burning captions in is not that. It is a queue with stages, and the tool surface has to admit it. A server that pretends otherwise — one blocking edit_video call — gets killed by the client's timeout while the render carries on, orphaned and billed.

This page is written for whoever is integrating, not for whoever is buying. It assumes you know what a tool call is; if you do not, What Is MCP? Model Context Protocol Explained and MCP vs Function Calling: What Actually Differs are the right starting points. ClipSpeedAI's server at https://api.clipspeed.ai/mcp appears throughout as the specimen on the table, because its ten tools split cleanly along the identifier line and because its schemas are readable over curl in one command. Read every payload shape below as an illustration of a pattern — the authoritative description of any tool is the inputSchema the server returns, and I will keep saying so.

On this pageTwo Identifiers, and Why Everything Follows From ThemWhat Actually Travels Over the WireFive Properties of Video That Break an Ordinary ToolReading the Ten Tools as a GrammarThe Contract Behind submit_to_clipspeed and check_clipsWhere the Bytes GoKeys: csai_live_, Request Counters, and Revocation That RevokesPointing a Client at the EndpointDebug With curl Before You Blame the ClientA Dependency-Free Node Inventory ScriptPython, With a Poll Loop That Gives UpLive Sessions: subscriptionId, monitoring, and Calling Stop TwiceMCP or the REST API for This Particular JobBeliefs That Produce Broken IntegrationsWhere I Would Not Point This ToolingA Week of Clipping, Written Out as an Agent Loop

Two Identifiers, and Why Everything Follows From Them

Start with the split, because it explains the whole tool list. A recorded video has an end. You can hand it over, walk away, and come back to a finished set of clips. That is a job, and a job needs exactly two verbs: one to start it and one to ask about it. On ClipSpeedAI those are submit_to_clipspeed and check_clips, and the token that connects them is a projectId.

A live stream has no end you know in advance. There is nothing to wait for, because the thing is still happening. So it is not a job — it is a session, with a lifetime you are responsible for. Sessions need four verbs: open, ask, extend, close. On ClipSpeedAI those are clip_livestream, check_livestream, extend_livestream and stop_livestream, and the token is a subscriptionId.

Six of the ten tools are accounted for by that distinction alone. The practical consequence for anyone writing agent code is that the two identifiers are not interchangeable and the polling semantics differ in a way that will bite you: a job's check tool eventually reports a terminal state, and a session's check tool never does — a session reporting monitoring means the stream is still live and clips are still accumulating. An agent that treats the first non-empty clip list as "done" will confidently report four clips from a stream that produces forty. Hold that thought; there is a whole section on it below.

The remaining four tools are not about time at all. discover_trending finds input. list_templates constrains style. creator_pack enriches output. publish_to_youtube emits it. Only that last one leaves the building.

What Actually Travels Over the Wire

MCP is JSON-RPC 2.0 with a small, fixed vocabulary. Three methods carry the weight for video work. initialize negotiates a protocol revision and exchanges capabilities. tools/list returns every tool the server exposes, each with a name, a natural-language description, and a JSON Schema for its arguments. tools/call invokes one by name with an arguments object. Servers may also publish resources and prompts; for a clipping server those are decoration.

The payoff is that discovery happens at runtime rather than in a README. A client that has never heard of ClipSpeedAI can connect, ask what exists, read the schemas, and construct a valid call — which is precisely why one server implementation reaches many clients without per-client code. How MCP Servers Work: Architecture and Request Flow covers the handshake sequence in more detail than belongs here.

Two transports are in circulation. A local server runs as a child process of the client and talks over stdio; it lives and dies with that process. A remote server exposes an HTTP endpoint and speaks streamable HTTP, which means a response may arrive as a plain JSON body or as a server-sent-events frame, and a session identifier may be handed back in a response header for subsequent requests to echo. Video services are remote, and not by preference — a laptop is a poor host for encoding pipelines, and a server that dies when someone closes their editor is a server that loses renders. Remote MCP vs Local MCP Servers argues the general case; for video the argument is short.

Five Properties of Video That Break an Ordinary Tool

If you have built MCP servers over databases or filesystems, the instincts you formed there will produce a broken video server. Five properties are responsible.

Each of those pushes the same direction: state lives on the server, the call returns immediately, and the identifier is the contract.

Reading the Ten Tools as a Grammar

It helps to read a tool list the way you would read a small language — what are the verbs, and what do they operate on. Here is ClipSpeedAI's, grouped by function rather than alphabetically, using the tools' own descriptions rather than my gloss on them.

Finding input. discover_trending finds the fastest-growing recent video in a niche to turn into shorts. Note the built-in constraint: it searches only videos published in roughly the last three weeks. That is a design decision worth respecting rather than working around — a video that has been up for a year has already been clipped by everyone who was going to.

Starting work. submit_to_clipspeed drops a video URL (or a file) into ClipSpeed. It is the clip button, and it is the only tool that starts a recorded job.

Reading results. check_clips returns the finished, scored, captioned 9:16 vertical clips for a projectId — each one carrying a title, a viral score, and a download URL. The score is a ranking signal the service computes; treat it as ordinal and do not assume a published range or a threshold, because none is documented.

Choosing style. list_templates lists the caption-style templates. The real ids are exactly karaoke, hormozi, beasty, fire, youshaei and cinematic, and the chosen one is passed as captionStyle. Two useful facts follow: the set is small enough to memorize, and a typo in that field is a name that does not exist rather than a silently different look.

Enriching output. creator_pack returns, per clip for a projectId, suggested titles, hooks and best posting times. It is the tool that turns a folder of files into something postable.

Emitting. publish_to_youtube publishes a finished clip to YouTube and defaults to private. It takes a projectId, and optionally a clipId, a title and a privacyStatus. That default is the single most important safety property in the toolset — the failure mode of an over-eager agent is a private upload, not a public one.

The live four. clip_livestream opens a real-time session and returns a subscriptionId. check_livestream polls one. stop_livestream ends one, keeping the clips already made and leaving them downloadable. extend_livestream lengthens an active session.

Now notice what is absent. There is no trim(start, end), no track, no keyframe, no per-frame anything. The server exposes outcomes, not a timeline. That is a deliberate trade discussed near the end of this page, and it is the main reason a clipping MCP server is small enough for a model to use well. MCP Tool Design: Writing Tools an Agent Can Actually Use makes the general argument for keeping toolsets short.

The Contract Behind submit_to_clipspeed and check_clips

The recorded path is a three-step contract, and once you have seen it you can read any video MCP server in five minutes.

  1. Submit. Accept a source and options, validate what can be validated synchronously — a malformed URL should be rejected now, not by a worker several stages later — and return an identifier plus an initial state. Return fast; this call is a handshake, not the work.
  2. Poll. A separate tool takes the identifier and reports where things stand, returning results once they exist. States should be a small closed vocabulary the model can branch on, not free-form English.
  3. Fetch. Results are URLs with metadata attached. The agent ranks and presents; the user or a downstream process retrieves the bytes.

Read the trace below as a shape, not as a payload. The intervals are relative and deliberately unlabelled, because wall-clock depends on the source and no render-time figure is published. The field names are generic — id, state, clips — and are not ClipSpeedAI's response keys. Do not hardcode anything you read here, or anywhere else that is not a schema; get the real names from tools/list and from one real result.

t0 tools/call submit -> { id: "…", state: "queued" }
t0 + i tools/call check -> { state: "running" }
t0 + 2i tools/call check -> { state: "running" }
t0 + n·i tools/call check -> { state: "done", clips: [ … ] } i = your backoff interval, chosen by you n = unknown in advance; bound it with a deadline, not with hope

Cadence is the agent's responsibility, and agents are poor at it in two opposite directions: a tight loop that burns tokens on identical answers, or a single check followed by amnesia. A server can help by returning a suggested wait alongside the state. A client can help by wrapping the poll in explicit backoff with a hard deadline, which both code samples below do.

The failure mode worth engineering against is the duplicate submit. Picture it: the client's timeout fires on a submit that the server actually accepted, the agent sees an error, the agent retries, and now two renders of the same podcast are in the queue. Accept a caller-supplied idempotency value, or deduplicate on (account, source, options) inside a short window. This single decision removes an entire genre of support ticket.

Where the Bytes Go

Two boundaries run through any video MCP deployment, and keeping them apart is what lets the design survive a 4 GB source file. The protocol boundary is JSON only. The media boundary is ordinary HTTPS, usually against object storage with signed URLs. Nothing large ever crosses the first one.

 agent client MCP endpoint (HTTPS) render workers finished clips ------------ -------------------- -------------- -------------- tools/list ---> tool schemas <--- tools/call ---> validate, enqueue ---> transcribe submit_to_ return projectId score moments clipspeed <--- reframe to 9:16 render captions ---> clip files tools/call ---> read project state + download URLs check_clips <--- titles · scores · URLs <----------------------------------+ | browser / curl ============ plain HTTPS GET, no MCP involved ====================+

Two consequences people trip over. First, an agent never "has" the video — it has a link, which is why it can describe and rank clips without downloading anything, and why a model with no vision capability is still perfectly useful in this loop. Second, download URLs from object storage are frequently time-limited. An agent that caches a URL in its context and hands it back an hour later may be handing back an expired link; re-read from check_clips rather than from memory.

Keys: csai_live_, Request Counters, and Revocation That Revokes

Credentials come in two shapes and the right one depends on the client. GUI clients that support OAuth should use it — the user authorizes interactively and no long-lived secret is pasted anywhere. CLI and config-driven clients use a Bearer API key in an Authorization header.

ClipSpeedAI's keys are specific enough to be worth stating exactly, because half of all "it will not connect" reports are a mangled key:

That last point makes per-agent keys genuinely useful rather than merely tidy. One key per machine or per automation means a leak is contained, an unexpected counter is attributable, and revoking one thing does not break everything. Store keys in environment variables rather than literals; assume any key written into a config file is readable by every process running as that user, and rotate after that file is shared, backed up or handed to a contractor.

Then think about blast radius rather than secrecy alone. Most of this toolset reads, or produces private artifacts. publish_to_youtube is categorically different — it emits on someone's behalf — and while its private default is a strong guardrail, privacyStatus is a parameter, and parameters are exactly what a model chooses. Put a human between discovery and publication. Video titles and descriptions arriving from discover_trending are untrusted text entering a model's context, which is the classic prompt-injection surface; MCP Security: Scopes, Keys and Safe Tool Design and MCP Authentication: OAuth and Bearer Keys work through the threat model properly.

Pointing a Client at the Endpoint

One HTTP endpoint, one credential, many clients. For Claude Code the canonical command is a single line, and this is the only configuration on this page I will print verbatim:

claude mcp add --transport http clipspeed https://api.clipspeed.ai/mcp \ --header "Authorization: Bearer <API_KEY>"

GUI clients that support OAuth take a different route: add the endpoint as a custom connector and authorize in the browser, so no key is copied by hand at all.

For every other client — Cursor, Codex, Windsurf, OpenClaw, Hermes, ChatGPT — the instruction in prose is: add ClipSpeedAI as an HTTP MCP server pointed at https://api.clipspeed.ai/mcp, with your key supplied as an Authorization: Bearer header, following that client's own MCP documentation. I am deliberately not printing a config file for those. Field names differ between clients, and so does whether a ${VAR} reference in a config file is expanded at all — several require the literal key, and a client that does not expand it will happily send the variable name as your bearer token and produce an authentication error you will spend an hour misreading. Use each client's documented format.

Support is not uniform, and the distinction between "we drove the whole thing end to end" and "it speaks the same protocol" is worth being exact about:

ClientStatusHow it connects, and where the walkthrough lives
Claude (claude.ai)Fully supportedOne-click OAuth custom connector — ClipSpeedAI MCP for Claude (claude.ai): Complete Setup Guide
Claude CodeFully supportedThe claude mcp add line above; fastest path — ClipSpeedAI MCP for Claude Code: Complete Setup Guide
Claude DesktopFully supportedDesktop connector setup, step by step in ClipSpeedAI MCP for Claude Desktop: Complete Setup Guide
WindsurfFully supportedHTTP server plus Bearer key, in Windsurf's own format — ClipSpeedAI MCP for Windsurf: Complete Setup Guide
CursorCompatibleSame protocol; verification in progress. Follow ClipSpeedAI MCP for Cursor: Complete Setup Guide
CodexCompatibleSame protocol; verification in progress. Follow ClipSpeedAI MCP for Codex CLI: Complete Setup Guide
OpenClawCompatibleSame protocol; verification in progress. Follow ClipSpeedAI MCP for OpenClaw: Complete Setup Guide
HermesCompatibleSame protocol; verification in progress. Follow ClipSpeedAI MCP for Hermes Agent: Complete Setup Guide
ChatGPTRolling outConnector availability is vendor-gated and unverified — ClipSpeedAI MCP for ChatGPT: Complete Setup Guide

Choosing an editor for agent work more broadly is a separate question, taken up in Claude Code vs Cursor for MCP Workflows.

Debug With curl Before You Blame the Client

Nothing about MCP requires an agent, and that is a debugging superpower. When a client reports "connection failed" it has told you almost nothing — the network, the key, the header set and the client's own config parser are all still suspects. One curl eliminates three of them.

# Set this to the protocol revision your client implements.
# The server answers with the revision it agreed to — read that back.
export MCP_REV="<revision-your-client-implements>" curl -sS https://api.clipspeed.ai/mcp \ -H "Authorization: Bearer $CLIPSPEED_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d "{ \"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"initialize\", \"params\": { \"protocolVersion\": \"$MCP_REV\", \"capabilities\": {}, \"clientInfo\": { \"name\": \"curl\", \"version\": \"0.0.1\" } } }"

Three details account for most hand-rolled failures. The Accept header must permit text/event-stream, because a streamable HTTP server may answer with an SSE frame rather than a JSON body — omit it and you get a protocol error that looks like an auth error. The protocol revision is negotiated, so send what you implement and read back what was agreed rather than assuming. And the response may carry a session id header that later requests are expected to echo.

Then list the tools. This is the highest-value call against any MCP server, because it returns every name, description and input schema in one response:

curl -sS https://api.clipspeed.ai/mcp \ -H "Authorization: Bearer $CLIPSPEED_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

If both of those succeed and your client still fails, the fault is on the client side — most commonly its config format, or the fact that it read MCP config once at startup and has not been restarted since you edited it.

A Dependency-Free Node Inventory Script

An official SDK exists and is the right dependency for production code. What follows is deliberately dependency-free, because when something is wrong you want to see the wire format with nothing hidden behind an abstraction.

// node 18+; no dependencies
const ENDPOINT = "https://api.clipspeed.ai/mcp";
const KEY = process.env.CLIPSPEED_API_KEY; // Send the revision your client implements; the server replies with the
// revision it agreed to. Do not treat any literal here as authoritative.
const PROTOCOL_REVISION = process.env.MCP_REV; let sessionId = null; async function rpc(method, params, { notification = false } = {}) { const body = notification ? { jsonrpc: "2.0", method, params } : { jsonrpc: "2.0", id: Date.now(), method, params }; const headers = { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json", "Accept": "application/json, text/event-stream" }; if (sessionId) headers["Mcp-Session-Id"] = sessionId; const res = await fetch(ENDPOINT, { method: "POST", headers, body: JSON.stringify(body) }); const sid = res.headers.get("mcp-session-id"); if (sid) sessionId = sid; if (notification) return null; const text = await res.text(); // streamable HTTP may answer as SSE: take the last data: line if (text.startsWith("event:") || text.includes("\ndata:")) { const line = text.split("\n").filter(l => l.startsWith("data:")).pop(); return JSON.parse(line.slice(5).trim()); } return JSON.parse(text);
} const init = await rpc("initialize", { protocolVersion: PROTOCOL_REVISION, capabilities: {}, clientInfo: { name: "inspect", version: "0.0.1" }
});
console.log("server agreed to:", init.result.protocolVersion); await rpc("notifications/initialized", {}, { notification: true }); const { result } = await rpc("tools/list", {});
for (const t of result.tools) { console.log(t.name); console.log(" ", t.description); console.log(" args: ", Object.keys(t.inputSchema?.properties ?? {})); console.log(" required:", t.inputSchema?.required ?? []);
}

Run that and you have a self-documenting inventory of any MCP server, printed from the server's own mouth. Calling a tool uses the same helper with method: "tools/call" and params: { name, arguments }, where every key in arguments comes from the schema you just printed — including captionStyle, whose accepted values you can cross-check against list_templates rather than guessing.

Python, With a Poll Loop That Gives Up

The same client in Python, plus the piece the Node sample leaves out: a bounded wait. Notice that the tool-call helper refuses to invent argument names — you fill them from the schema.

import json, os, time, requests ENDPOINT = "https://api.clipspeed.ai/mcp"
# The revision your client implements; read back what the server agreed to.
PROTOCOL_REVISION = os.environ["MCP_REV"] HEADERS = { "Authorization": f"Bearer {os.environ['CLIPSPEED_API_KEY']}", "Content-Type": "application/json", "Accept": "application/json, text/event-stream",
} session_id = None
_next_id = 0 def rpc(method, params=None, notification=False): global session_id, _next_id payload = {"jsonrpc": "2.0", "method": method, "params": params or {}} if not notification: _next_id += 1 payload["id"] = _next_id headers = dict(HEADERS) if session_id: headers["Mcp-Session-Id"] = session_id r = requests.post(ENDPOINT, headers=headers, json=payload, timeout=60) r.raise_for_status() if "mcp-session-id" in r.headers: session_id = r.headers["mcp-session-id"] if notification: return None text = r.text if text.lstrip().startswith(("event:", "data:")): line = [l for l in text.splitlines() if l.startswith("data:")][-1] return json.loads(line[5:].strip()) return r.json() init = rpc("initialize", { "protocolVersion": PROTOCOL_REVISION, "capabilities": {}, "clientInfo": {"name": "inspect", "version": "0.0.1"},
})
rpc("notifications/initialized", notification=True) for t in rpc("tools/list")["result"]["tools"]: props = (t.get("inputSchema") or {}).get("properties", {}) print(t["name"], "->", sorted(props)) def call(name, arguments): """arguments must match that tool's inputSchema exactly.""" return rpc("tools/call", {"name": name, "arguments": arguments}) def poll(fetch, done, deadline_s=3600, start=10, step=10, cap=60): """fetch() -> result; done(result) -> bool. Backoff with a hard stop.""" waited, interval = 0, start while waited < deadline_s: result = fetch() if done(result): return result time.sleep(interval) waited += interval interval = min(interval + step, cap) raise TimeoutError("gave up waiting; the job may still be running")

Two things about poll earn their place. The interval grows, so a long render does not generate a hundred identical checks. And the deadline is absolute, so a job that never reaches a terminal state fails your process rather than pinning it forever. The done predicate is a parameter for a reason — you write it against the real result shape after you have looked at one, not against a shape you read on a web page.

Live Sessions: subscriptionId, monitoring, and Calling Stop Twice

Now the other half of the identifier split, which is where most integrations quietly misbehave. clip_livestream puts the server on a running stream and returns a subscriptionId. From that moment there is a thing consuming resources on your behalf, and nothing will end it except time or you.

clip_livestream(stream URL) -> subscriptionId | | stream is live; clips accumulate v
check_livestream(subscriptionId) | |-- status "monitoring" = still live, still clipping, NOT finished | +-- want longer? ----> extend_livestream(subscriptionId) | +-- done or ended ----> stop_livestream(subscriptionId) clips already made are kept and stay downloadable

Three rules that hold for any session-shaped tool, stated here in terms of these four:

Treat monitoring as "not yet", never as "here is your answer". This is the failure I would bet on finding in an unreviewed integration. The check tool returns what exists so far. An agent that summarizes the first response and moves on has not clipped a stream, it has sampled the first few minutes of one.

Bound the session deliberately and extend on purpose. The existence of extend_livestream as a separate tool is the point — continuing is an explicit decision by the agent or the user, not a default. A session nobody ends is compute nobody asked for.

Make stop safe to call twice. Agents lose track of state, re-read their own transcript, and call stop again. Because stopping keeps the clips already made, a second stop should be a no-op rather than anything destructive — and your agent code should be equally relaxed about receiving an "already stopped" response.

One more asymmetry: a stream can end on its own, without your agent doing anything. Your loop needs a branch for "the session's status says the stream is over" that is distinct from "I decided to stop". Livestream Clipping API: Clip While You Stream goes further into the lifecycle.

MCP or the REST API for This Particular Job

MCP does not replace a REST API — in most deployments it sits in front of one. The real question is which surface a given caller should use, and it has a clean answer: does a decision need to be made at runtime by something that can read?

DimensionMCP serverREST API
CallerA model choosing what to do nextCode that already knows what to do
DiscoveryAt runtime, via tools/listOut of band: docs, spec, SDK
Adding a new clientNothing to write — it speaks the protocolAn HTTP client per language
Argument validationJSON Schema published to the callerServer-side; caller may never see it
Long jobsMust be split into submit and check toolsFree choice: webhooks, long poll, SSE
DeterminismModel picks the tool and the argumentsFully deterministic
SuitsConversational, exploratory, one-off workScheduled pipelines, high-volume batch

The honest summary: if a person is in a conversation and the next step depends on what came back — which clip scored best, whether the stream is still live, whether hormozi or cinematic suits this creator — MCP earns its cost. If you are processing ten thousand videos on a cron, a model in the loop adds latency, token spend and variance in exchange for nothing. MCP vs REST API: When to Use Each works the decision through; Video Clipping API for Developers and AI Clipping API: Programmatic Short-Form Video cover the non-agent route.

Beliefs That Produce Broken Integrations

Each of these is a specific wrong belief with a specific consequence, which is more useful than a list of definitions.

Where I Would Not Point This Tooling

A reference that only lists strengths is marketing. Several jobs are a bad fit for an agent-plus-clipping-server, and recognizing them early saves a week.

There is an architectural cost worth naming too. Exposing outcomes rather than primitives means you get exactly what the service is good at and nothing else. A tool that returns captioned 9:16 clips cannot be talked into a 1:1 crop with no captions unless a parameter for that exists — the model can ask, but there is nothing to ask with. Composability is traded for reliability. For clipping that trade is correct, because the alternative is a model assembling a timeline one primitive at a time and getting it subtly wrong. For post-production it is the wrong trade entirely.

A Week of Clipping, Written Out as an Agent Loop

Here is the whole thing assembled, for a creator running a weekly routine. Each numbered step is one or more tools/call invocations, and every claim about what a tool returns is deliberately hedged to "whatever its schema exposes".

  1. Find the source. discover_trending surfaces the fastest-growing recent video in a niche. Do not re-implement a recency filter on top of it — the tool already limits itself to roughly the last three weeks. Filter the returned candidate on whatever fields the schema actually exposes, and nothing more.
  2. Fix the look before spending anything. Call list_templates and pick from what comes back, so the captionStyle you pass is a name that exists. The ids are karaoke, hormozi, beasty, fire, youshaei and cinematic; naming one that is not on that list is a mistake you would rather catch here than after a render.
  3. Submit. submit_to_clipspeed on each source, collecting the projectId each returns. Submit in parallel; poll serially. Guard against double submission before you write the retry logic, not after.
  4. Poll with backoff and a deadline. Use the loop from the Python section. Report per-project failures individually — one dead source URL should not sink a batch of five.
  5. Fetch and rank. check_clips against each projectId returns finished 9:16 clips with a title, a viral score and a download URL. Rank within the project by score and present a handful with their titles, not a wall of links.
  6. Dress the winners. creator_pack returns per-clip suggested titles, hooks and best posting times for a projectId. This is where a folder of MP4s becomes a posting schedule.
  7. Stop, and ask. Publication is a separate step with a person in it. publish_to_youtube defaults to private, which is a good default to leave alone until someone has actually watched the clip.
discover_trending(niche) | v
list_templates() ---> captionStyle = "hormozi" | v
submit_to_clipspeed(url, captionStyle) -> projectId | | backoff + deadline v
check_clips(projectId) -> clips: title · viral score · download URL | +--> creator_pack(projectId) -> titles · hooks · posting times | v [ human reviews ] --> publish_to_youtube(projectId, clipId, …) privacyStatus defaults to private

The live variant swaps steps 3 through 5 for a session: open with clip_livestream, check periodically while the status reads monitoring, extend if the stream runs long, stop when it ends — and remember that clips made before the stop survive it. AI Agent Video Automation: End-to-End Workflows expands both variants, MCP for Creators: Automating Video Without Code covers the same ground without the code, and Best MCP Servers for Video and Content Workflows is the wider survey if you are still comparing options. If you are building a server rather than calling one, How to Build an MCP Server (Practical Guide) is the counterpart to this page.

On cost, so the plan is not a surprise at step 3: there is no free plan. One dollar starts a three-day trial — a single $1 charge today, converting to your chosen plan after three days unless cancelled. Plans are Starter at $15/mo, Pro at $29/mo and Ultra at $49/mo, with annual billing saving 50%. Which, given how much of this page has been telling you not to trust printed payloads, is the right first move anyway.

Frequently asked questions

What does an MCP clipping tool hand back if not the video?
An identifier. For a recorded source, submit_to_clipspeed returns a projectId that you later pass to check_clips; for a live stream, clip_livestream returns a subscriptionId that the other three live tools operate on. Finished clips come back as download URLs with a title and a viral score attached, and the bytes travel over ordinary HTTPS rather than through the JSON-RPC connection. Keeping media out of the protocol is what lets the same design handle a five-minute upload and a three-hour stream.
What does a ClipSpeedAI API key look like, and can I get it back if I lose it?
A key is the literal prefix csai_live_ followed by 48 hexadecimal characters. You cannot retrieve it later — only the first 18 characters are stored for display, so the full value is shown once at creation. That is not a problem in practice, because generating a replacement is a POST to /auth/api-keys and revoking the lost one is a DELETE to /auth/api-keys/:id, which marks it inactive and stamps a revoked timestamp. Each key also carries its own rate limit and running request counters, which makes per-machine keys genuinely useful rather than merely tidy.
How do I choose a caption style, and what happens if I get the name wrong?
Call list_templates and pass the id you get back as captionStyle. The real ids are exactly karaoke, hormozi, beasty, fire, youshaei and cinematic. Because the set is a small closed list, a wrong value is a name that does not exist rather than a silently different look — which is why reading the templates before submitting is worth the extra call in an automated loop.
Why does a live status of 'monitoring' not mean the job is running toward completion?
Because a live session has no completion condition. A status of monitoring means the stream is still live and still being clipped, and check_livestream returns the clips produced so far, not a final set. An agent that treats the first non-empty response as finished will report a handful of clips from a stream that eventually produces many more. Recorded jobs behave the opposite way: they do reach a terminal state, which is exactly why the two paths use different identifiers and different tools.
Is it safe to let an agent call publish_to_youtube?
With a person in the loop, yes. The tool defaults to private, which is a strong guardrail — the failure mode of an over-eager agent is an unlisted upload, not a public one. But privacyStatus is a parameter, and parameters are what a model chooses, so put an explicit confirmation between selecting a clip and publishing it. There is a second reason: video titles and descriptions arriving from discovery are untrusted text entering the model's context, so a chain that runs from discover_trending straight through to publishing is a prompt-injection path with a public endpoint on the far side.
My client says the server will not connect. Where do I start?
Bypass the client entirely and call the endpoint with curl: an initialize request with an Authorization header, Content-Type application/json, and an Accept header that permits both application/json and text/event-stream, followed by tools/list. Missing the event-stream part of Accept produces a failure that reads like an auth error and is not. If curl succeeds and the client still fails, the fault is the client's config format or its startup caching — most clients read MCP config once at launch, so restart before drawing any conclusion.
Should I copy the JSON payload shapes shown in articles like this one?
No, and that includes this page. The polling traces here use generic field names to illustrate a pattern, not ClipSpeedAI's actual response keys, and no render-time figure in any illustration should be read as a published number. The authoritative source is tools/list, which returns every tool's description and full input schema, plus one real result you have looked at. Write your code against those two things.
Does discover_trending search the whole of YouTube's history?
No. It looks for the fastest-growing recent video in a niche, and it searches only videos published in roughly the last three weeks. That constraint is built into the tool rather than something you pass, so an agent does not need to layer its own recency filter on top — and should not, since anything older has usually been clipped already by everyone who intended to.
When is calling the REST API directly the better choice?
Whenever no decision has to be made at runtime. Scheduled batches, high-volume pipelines and anything needing reproducible output are better served by your own code calling the underlying API — a model in the loop adds latency, token cost and variance without adding judgment you need. MCP pays for itself when the next step genuinely depends on what the last step returned: which clip scored highest, whether the stream is still live, which caption style suits this creator.

Related reading

ClipSpeedAI MCP on claude.ai: The No-Config ConnectorClipSpeedAI MCP for Claude Code: Terminal Setup, Keys and Tool ReferenceClipSpeedAI MCP for Claude Desktop: Complete Setup GuideClipSpeedAI MCP in Windsurf: Bearer Key Setup for CascadeClipSpeedAI MCP in Cursor: Connect the Clipping Engine to Your Editor AgentClipSpeedAI MCP for Codex CLI: HTTP Setup and Tool ReferenceClipSpeedAI MCP for OpenClaw: Complete Setup GuideClipSpeedAI MCP on Hermes Agent: Connect and Verify
Start clipping for $1 →