Skip to content
The MCP server

Long-form video from your MCP client

Most MCP video servers make 15-second clips. This one makes ten-minute videos — script, voice, storyboard, images, assembly, thumbnail, and a quality gate that can refuse to ship one.

There is no MCP price. Calls spend the credits already on your plan, at the same rate as the app. Connect Claude, ChatGPT, Cursor or any other client that speaks MCP over HTTP. It is the same account you sign in to here, the same balance and the same limits, reached from a different client. The connector is included on Studio ($199/mo) and Agency ($499/mo).

Connect a client

Add the server as a remote MCP server in your client. Your exact URL is on Settings → Connections with a Copy button beside it — it is your deployment's HTTP address with /mcp on the end.

Server URL
https://<your-deployment>.convex.site/mcp
  • The first call your client makes has no token, so it is answered with HTTP 401 and a WWW-Authenticate header pointing at the OAuth metadata. Your client reads that, registers itself, and opens a browser.
  • Registration is dynamic (RFC 7591): there is no form to fill in and no client id to paste. Registering proves nothing and grants nothing — the approval screen is the boundary, not the registration.
  • You sign in here, and Octana shows you which client is asking, what it will be able to do and what it will not. Approving hands your client an authorization code, good for 10 minutes and usable once; it exchanges that for a token. Authorization is OAuth 2.1 with PKCE, and S256 is the only challenge method accepted.
  • Tokens last 30 days and are revocable from Settings → Connections at any time. Disconnect stops the client's next call, with no deploy and no waiting.
  • Redirect URIs must be https, or http on localhost or 127.0.0.1 — the two exceptions desktop clients need. They are matched exactly at authorize time, never by prefix.

A connected client can spend your credits

Some of the tools start work that costs money, and a model in a loop is the caller most likely to start it more than once. The rate limits are the same ones a /v1 key is subject to on this account — there is no separate MCP allowance, deliberately — and Disconnect is the kill switch.

The tools

12 tools, and this section is all of them: 6 that only read and 6 that change something. The list is deliberately short — a client that has to read twenty descriptions before every turn picks the wrong one. Reading is always free; the tools that spend credits say so in their own description, which is the same text your client is sent.

create_long_video takes 8 to 30 minutes. The floor is higher than the app's on purpose: long-form is what this server is for, and a floor is how the description stays true when a model reads it.

WRITES

create_long_video

jobs:write

Start a long-form video

Start a fully produced 8-to-30 minute video from a topic: script, voiceover, storyboard, images, assembly and thumbnail, with a quality gate that can refuse to ship one. Returns a job id immediately; it takes roughly fifteen minutes. This spends credits — call estimate_cost first to see how many.

Same authority as POST /v1/videos.

READS

get_video_status

jobs:read

Check a video

Where a job has got to: stage, progress, what each finished stage cost, and the URLs when it is done. Also reports a quality-gate refusal and the refund that came with it.

Same authority as GET /v1/videos/:id.

READS

list_videos

jobs:read

List videos

Recent jobs, newest first, up to 25. Id, title, status and what each has cost.

Same authority as GET /v1/videos.

WRITES

cancel_video

jobs:write

Cancel a video

Stop a running job. Stages already finished keep their credits — cancelling does not refund work that was delivered — but nothing further is started or charged.

Same authority as POST /v1/videos.

WRITES

retry_stage

jobs:write

Retry a stage

Run one failed stage again without re-running the whole job. The retried stage spends credits at its normal rate; the stages around it are not re-charged.

Same authority as POST /v1/videos.

WRITES

write_script

tools:run

Write a script

Write a retention-engineered YouTube script to an exact word target — spoken narration only, no scene directions. Returns a summary, a word count and a URL; the full text is not inlined. This spends credits.

Same authority as POST /v1/scripts.

WRITES

run_tool

tools:run

Run any tool

Run one of the account's tools by id — voiceover, images, thumbnails, captions and the rest. list_tools returns the ids and each tool validates its own input. This spends credits.

Same authority as POST /v1/tools/:toolId.

READS

list_tools

jobs:read

List tools

Every tool run_tool can run: id, name and group. Read-only and free.

Same authority as GET /v1/tools.

READS

estimate_cost

billing:read

Estimate a video's cost

What a video of a given length would cost, broken down by stage, against the current balance. No side effects and nothing is charged. Call this before create_long_video.

Same authority as GET /v1/me.

READS

credit_balance

billing:read

Read the credit balance

Credits available now, the plan they came with, and where to top up.

Same authority as GET /v1/me.

READS

list_channels

billing:read

List channels

The account's channels and their ids. A job given a channel inherits its locked style and voice, so this is what create_long_video's channelId needs.

Same authority as GET /v1/me.

WRITES

get_export_pack

jobs:read

Build the editor export pack

Build and link the six-file editor pack for a finished job — timeline CSV, markers, SRT and VTT captions, the script and a manifest — so it can be opened in Premiere, Resolve or Final Cut. It costs no credits.

Same authority as GET /v1/videos/:id.

The descriptions above are what your client is sent verbatim in tools/list, and a listing only includes the tools your grant's scopes cover — a read-only client does not see the ones it could not call. Inputs are JSON Schema, generated from the same schemas that validate the arguments server-side, so a call that matches the schema is a call that is accepted.

What a result looks like

Every tool returns one block of text, written as a sentence your client can relay and you can read. Not a JSON dump, and never a whole script: a ten-minute script is about 1,500 words, and a tool that returns nine kilobytes of prose fills the model's context with the thing it was supposed to hand over. Scripts and transcripts come back as a word count and a URL.

create_long_video
Started a 12-minute video on "How compound interest actually works". Job id: j57f2c9m4k1p8q3r6t0v · estimated 230 credits · balance after: 7,370. It takes about fifteen minutes. Check it with get_video_status. Track it at https://your-app-host/dashboard/jobs/j57f2c9m4k1p8q3r6t0v
get_video_status — still running
"How compound interest actually works": storyboard, 3 of 9 stages, 34% done. Started 4 minutes ago. 350 credits so far. Check again with get_video_status.
get_video_status — the quality gate refused it
The quality gate refused "How compound interest actually works". The hook restates the title and the middle third adds nothing. Net charge: 0 credits — you were not charged for what it did not deliver. Retry with a different angle, or open it at https://your-app-host/dashboard/jobs/j98d4b1x7n2m5k8j0h3g to see the score breakdown.
estimate_cost
A 12-minute video at 8 seconds a slide is about 230 credits ($0.76 of your allowance). Your balance is 7,600. Breakdown: Writing script 5 · Recording voiceover 61 · Storyboarding scenes 9 · Generating images 81 · Assembling video 24 · Designing thumbnails 50. Nothing was charged for this estimate.

The third one is the important one. A refused video costs nothing, the result says so in the same breath as the refusal, and the reason is the judge's own sentence rather than a generic failure — so you can tell a rejected video from a broken pipeline without opening the app. These four are rendered by calling the server's own result-shaping functions, with example ids and an example balance; the sentences are not transcripts.

Scopes and consent

The same four scopes an API key carries, because there is one scope vocabulary in this product and MCP does not get a second. A grant holds the ones you approved, they are checked on every tool call rather than once at connect time, and widening them means connecting the client again.

jobs:read

Read jobs

List jobs and read their status, stages and artifacts.

jobs:write

Create jobs

Launch videos. This spends credits.

tools:run

Run tools

Run any registered tool. This spends credits.

billing:read

Read billing

Balance, lots and ledger. Read-only.

The approval screen lists what the client will be able to do and, underneath, what it will not: publish to YouTube, buy credits, or clone a voice or train a face. That second list is not reassurance copy — there are no tools for any of it, which is why it can be promised.

What a call costs

There is no MCP price. Calls spend the credits already on your plan, at the same rate as the app. A video is charged per stage as each stage completes, at the cost the provider actually reported — not at the estimate. A tool run is charged once, when it returns.

  • There is no MCP plan, no MCP credit pack and no per-call fee. Nothing on the pricing page changes because you connected a client.
  • estimate_cost has no side effects and costs nothing. Call it before anything that writes. 12 minutes at one image every 8 seconds estimates 230 credits — the same arithmetic the Create page shows before you spend anything.
  • A video the quality gate refuses costs nothing, and get_video_status reports the net figure, so you can see it from the client rather than taking it on faith.
  • Calls that run on your own provider keys charge zero platform credits, over MCP exactly as in the app.
  • Rate limits are counted per credential, and an MCP grant is a credential. The account's own ceilings still apply on top, so exhausting them from a script does refuse the MCP client. What the two do not share is a second allowance — a model in a loop is exactly the thing a second allowance would fund.
  • credit_balance returns the top-up URL for you to open. No tool buys anything.

Errors

Failures are JSON-RPC errors with a message written for whoever is reading the chat. Two of them are not JSON-RPC errors at all and cannot be, because a client has to see them at the HTTP layer.

TypeAnswered asWhat it means
authentication_errorHTTP 401No token, or one that is expired, revoked or not yours. Answered at the HTTP layer rather than as a JSON-RPC error, carrying a WWW-Authenticate header that names where the OAuth metadata lives. That header is how your client discovers the sign-in flow, and it is the reason this one cannot be a JSON-RPC error.
permission_error-32001The grant does not carry the scope this tool needs. The message names the scope. Connect the client again to approve a wider set.
invalid_request_error-32602The arguments failed the tool's schema. The message names the field that was wrong.
not_found_error-32602No such job, artifact or channel. A job that does not exist and a job belonging to someone else return the same message, so this cannot be used to find out whose job ids exist.
conflict_error-32603The same work is already in flight. Read the status rather than starting it again.
rate_limit_error-32603A ceiling refused the call, and the message names which one and when the next call can run. These are the account's own buckets — the same ones a /v1 key uses. MCP has no allowance of its own.
insufficient_credits-32603The balance cannot cover the estimate. The message states what is needed and what is available. Nothing was started and nothing was charged.
feature_disabledHTTP 503The connector is switched off on this deployment. Returned before the body is parsed, so it is not a JSON-RPC error either.
server_error-32603Something failed on our side and it has been logged.

The type strings are the ones the /v1 API returns, on purpose: one vocabulary for both doors, so a client and a script cannot disagree about what happened. Two protocol-level codes sit alongside them — -32020 when the headers contradict the body, and -32022 when the revision is one this server does not speak. Both are defined by the specification, not by us, and the second carries the versions that would work.

Protocol

Streamable HTTP at POST /mcp, protocol revision 2026-07-28. A GET or DELETE on the same path answers 405 with Allow: POST. This is the only transport — there is no local server and nothing to install.

There is no initialize handshake

Revision 2026-07-28 removed it, along with protocol-level sessions. Every request carries its own version in _meta and in the mcp-protocol-version header, and each request is accepted or refused on its own — nothing is remembered between them. A client that opens with initialize is told so in a sentence, because for that client the error message is the only diagnostic it can show you.

  • Four methods: server/discover, tools/list, tools/call and ping. Anything else is -32601 with a message naming the four. server/discover returns the supported revisions, the capabilities and the server identity in one request, so a client can present this server without probing.
  • Supported revisions: 2026-07-28. Revisions from the handshake era are not supported, and a version mismatch comes back with the list of ones that would work rather than a bare refusal.
  • mcp-method is required on every request and must match the body's method. mcp-name is required on a tool call and must match the tool name in the body. A header that disagrees with the body is refused rather than reconciled — guessing which one the caller meant is how a proxy ends up calling a different tool from the one the client asked for.
  • Every call is one request and one response. There is no server-to-client stream and no long-lived connection to hold open: this revision removed the GET stream endpoint, and a video takes about fifteen minutes anyway, which is not a thing to hold a socket for. Poll get_video_status.
  • Results are content blocks — one text block per call. See what a result looks like.
  • Capabilities declare tools and nothing else. No resources, no prompts, no sampling and no roots — declaring a capability that is not implemented is how a client hangs waiting for an answer that never comes.

The revision, the header names and the supported list on this page are read from the server's own constants, so this page cannot describe a protocol the handler does not implement. This specification has moved more than once; when it moves again, both move together.

What this server does not do

Being specific about the edges is cheaper for both of us than finding them mid-conversation with a model that has already told you it can.

Nothing here publishes

There is no publish_now and no schedule_publish. A machine-made video stops before publish and waits for a person, because YouTube's developer policies require the account holder to have final control over what gets uploaded — and a chat client is the least supervised caller in the product. Approve and publish from the app.

Nothing here buys anything

No tool tops up credits. A model completing a purchase inside a chat turn, against a checkout you never see, is not a feature. When the balance is short the result says so and gives you the link.

Nothing here clones a voice or trains a face

Voice cloning needs a consent recording made by the person whose voice it is. A chat client cannot produce one, and it must not be able to claim it did. Those flows stay in the app.

No tool returns a full script or transcript

You get a word count and a URL. Returning 1,500 words into a chat turn fills the context with prose the model then summarises back at you — worse than the link, and more expensive.

No resources and no prompts

Tools only. MCP resources would duplicate what get_video_status already answers, under a second URI scheme with a second permission story.

There is no local server and no npm package

Remote HTTP only. There is nothing to install, nothing to keep in step with the backend, and no copy of this server on your machine that could fall behind it.

There is no unauthenticated mode

Every call resolves an identity first, including the read-only ones. A list of your projects is your content strategy; there is no read-only-so-it-is-fine subset here.

There is no directory listing to install from

Octana is not published as a ChatGPT app or in any client's app gallery. You add it by URL, in whichever client you already use. If that changes, this page will say so.

MCP cannot do anything the API cannot

Every tool names the /v1 route it is the MCP spelling of, and it is that route's scope check it passes through. It is a second door onto the same rooms, and it is meant to stay that way — the moment it is not, it is a second way into the pipeline with its own bugs.