transcodelyproduct updateMCPClaudeAI agents

Transcodely Now Has an MCP Server: Transcode Video From Claude

10 min read Dimitar Todorov

Transcodely runs a hosted MCP server at mcp.transcodely.com/mcp. Point Claude at it, authorize in the browser, and it can submit transcoding jobs, ingest and host videos, generate captions, and read back status, playback links, and spend — seven tools, no key to paste, no gateway to run.

Transcodely now runs a hosted MCP (Model Context Protocol) server at https://mcp.transcodely.com/mcp. Attach it to Claude — or any client that speaks remote MCP — authorize once in your browser, and you can transcode, host, and caption video by asking for it in plain language, without writing an API call or pasting a key.

There is nothing to install and no gateway to run. The server speaks MCP over streamable HTTP and exposes seven tools that wrap the parts of the API worth handing to an agent.

This post covers what shipped, what the tools actually do, and — the part I care more about — what I deliberately did not expose.

Why bother wrapping an API that already exists?

Because the friction in video work is almost never the encoding. It is the twenty minutes of remembering which origin ID you write outputs to, what the codec-times-container compatibility rules are, and whether the field is input_url or source_url.

That is exactly the shape of work a model is good at. It has read the docs. It can hold the schema. What it lacks is a way to actually reach the API — and MCP is the plumbing that closes that gap, without me shipping a bespoke integration per client.

So the honest framing: this is not a new capability. Every one of these tools was already reachable over REST. What is new is that the schema, the validation errors, and the ID formats now live somewhere Claude can read them, and it can act on them in the same conversation where you are already working.

What can Claude actually do?

Seven tools. Four only read; three create work and bill for it.

Tool What it does Effect
create_job Transcode a source from gs://, s3://, or https:// into 1–10 output renditions, written to a storage origin you own. Creates · billable
create_video_from_url Ingest a publicly reachable https:// video and host it — adaptive ladder, CDN, player. Creates · billable
generate_captions Transcribe a hosted video into a WebVTT subtitle track. Creates · billable
get_video Read a hosted video: status, visibility, duration, poster, every rendition, and a playback block once it is ready. Read-only
get_job_status Compact progress snapshot for one job — status, per-output status, error codes. Read-only
list_jobs Recent jobs newest first, optionally filtered by status, cursor-paged. Read-only
get_usage Encoding minutes, storage, egress, and cost in EUR for a billing month. Read-only

The tool descriptions are the product surface, so I wrote them the way I write API docs: defaults stated, constraints stated, enums lowercase and matching the wire contract. create_job’s description names the supported URL schemes and tells the model to use create_video_from_url instead if it wants something playable. That one sentence removes most of the wrong-tool guessing.

How do you connect it?

Register the server, then authenticate — no key anywhere:

claude mcp add --transport http transcodely https://mcp.transcodely.com/mcp

Run /mcp inside Claude Code, choose transcodely, pick Authenticate, and approve the screen your browser opens. Claude Code stores the token and refreshes it for you. In claude.ai it is Settings → Connectors → Add custom connector, paste the URL, click Connect. Cursor prompts you to authorize the first time a tool runs.

Because the browser flow carries no credential, a .mcp.json committed to a repo is just a URL — teammates each authorize with their own account:

{
  "mcpServers": {
    "transcodely": {
      "type": "http",
      "url": "https://mcp.transcodely.com/mcp"
    }
  }
}

For headless use — CI, a server-side agent, a container with no browser — there is no consent screen to complete, so pass an app-scoped API key as a bearer token instead. That path is documented in the connect guide, along with the per-app URL form (…/mcp/app_k1l2m3n4o5) you use to pin an agent to one app when you belong to more than one organization.

What does a real exchange look like?

Ask for a video to be hosted:

Transcode and host this video and give me a link: https://example.com/talk.mp4

Claude picks create_video_from_url and calls it:

{
  "url": "https://example.com/talk.mp4",
  "title": "Conference talk"
}
{
  "id": "vid_a1b2c3d4e5f6",
  "object": "video",
  "status": "processing",
  "visibility": "unlisted",
  "renditions": []
}

Nothing is playable yet — the encode has not run, so there is no playback block. It polls get_video until that changes:

{
  "id": "vid_a1b2c3d4e5f6",
  "object": "video",
  "status": "ready",
  "visibility": "unlisted",
  "duration_seconds": 187.4,
  "renditions": [
    { "resolution": "1080p", "codec": "h264", "bitrate_kbps": 4500 },
    { "resolution": "720p",  "codec": "h264", "bitrate_kbps": 2500 },
    { "resolution": "480p",  "codec": "h264", "bitrate_kbps": 1200 }
  ],
  "playback": {
    "player_url": "https://play.transcodely.com/v/vid_a1b2c3d4e5f6",
    "hls_url": "https://….b-cdn.net/…/hls/master.m3u8",
    "expires_at": "2026-08-27T18:00:00Z"
  }
}

player_url is the payoff: a durable page you can hand to a human, and it does not expire. hls_url is for embedding in your own player, and expires_at qualifies that URL alone — it says nothing about player_url. Private videos get the signed hls_url only; the player page does not serve them, so no player_url comes back. Results are abridged here, and in practice the agent polls a few times rather than once.

One thing worth flagging in that ladder: the auto-profile builds downward from your app’s resolution ceiling regardless of the source. Feed it a 720p file and you will still get a 1080p rung, upscaled. That is the ladder doing what it was configured to do, not the encoder finding detail that was never there.

What I deliberately did not ship

No delete, no cancel, no update. Nothing exposed over MCP can remove or modify data that already exists. Three tools create new work, four read. An agent that misreads your intent can cost you money; it cannot cost you your library. That asymmetry was the single biggest design decision here, and I would rather field “why can’t Claude cancel this job” than the alternative.

No reach beyond the seven tools. An authorized connection acts as you, inside the app it resolved to. It cannot touch admin, billing, team, or key-management surfaces, and it cannot escalate past your own membership. A video belonging to another app reads back as not found — not as a permission error, which would confirm it exists. An ak_… key presented at a different app’s URL is rejected outright.

No file upload. create_video_from_url fetches a public URL, and private or internal addresses are rejected as SSRF protection. Pushing bytes from your laptop still goes through the dashboard or the upload API.

The retry problem, and where I only half-solved it

Agents retry tool calls automatically and silently. If a call times out on the network but succeeded on my side, a naive retry bills you twice for the same work — and you would have no idea, because the retry never surfaced in the transcript.

generate_captions handles this properly. The idempotency key is derived from app + video + language, so repeating the call returns the job the first one created instead of creating and charging for a second. Ask for English captions three times and you are billed once.

create_job and create_video_from_url do not have that protection yet. A retried create is a new job and a new charge. In practice the failure window is narrow, but it is real, and I would rather write that sentence here than have you discover it on an invoice. Captions got it first because a silent double-charge on a per-source-minute fee is the most likely one to go unnoticed.

Every tool call also writes an audit row with scrubbed arguments, the error code, and duration — so if an agent does something surprising, there is a record of exactly what it called and with what. Billing follows the same rates as the REST API; going through an agent costs no more and no less.

Turning it off

Three ways, and they are not equivalent. Removing the connector in the client (claude mcp remove transcodely, or disconnecting it in claude.ai) is the one for a connection you simply no longer want. Removing the member from the organization is the one for someone leaving — membership is re-checked on every tool call, so access ends at their next request. Revoking the ak_… key covers the headless path only.

One honest caveat: an access token that was already issued stays valid until it expires, roughly ten minutes worst case. The client cannot mint a new one once the connector is gone or membership is removed, so it is a short tail rather than an open door — but if you need access to stop at a hard instant, remove the member and treat that token lifetime as the outer bound.

Where this sits against the alternatives

I am not first here, and the honest comparison matters more than the announcement. FFmpeg Micro’s MCP server also authenticates with OAuth 2.1 and PKCE, so we are even on connection ergonomics — but it exposes fifteen tools to my seven, including cancel, upload, a download-URL helper, and one-shot “run and wait” variants that block until a transcode finishes. On surface area that is genuinely ahead of where I am, and if you want an agent driving raw FFmpeg options and filter graphs, it is the better fit.

Transcodely’s MCP server is narrower on purpose: it is a front end to a managed encoding and hosting platform, so the tools speak in ladders, origins, hosted videos, and a monthly EUR bill rather than filter graphs. The seven tools are the ones where an agent saves you real work; the ones I left out are mostly the ones where it could do real damage.

Getting started

Run the claude mcp add command above, authorize in the browser, and ask Claude to transcode something. The MCP server page has the product overview and per-client connect steps in one place, the connect guide is the reference version, and if you want the walkthrough with real prompts and the workflows worth wiring up, that post lands on the blog later this week.

As always, if you hit something weird, email me directly — still a one-person company, still the guy who wrote the code.

Happy transcoding.

Topics

transcodelyproduct updateMCPClaudeAI agents

Share this article