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).
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.
Type
Answered as
What it means
authentication_error
HTTP 401
No 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
-32001
The 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
-32602
The arguments failed the tool's schema. The message names the field that was wrong.
not_found_error
-32602
No 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
-32603
The same work is already in flight. Read the status rather than starting it again.
rate_limit_error
-32603
A 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
-32603
The balance cannot cover the estimate. The message states what is needed and what is available. Nothing was started and nothing was charged.
feature_disabled
HTTP 503
The connector is switched off on this deployment. Returned before the body is parsed, so it is not a JSON-RPC error either.
server_error
-32603
Something 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.
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.