API documentation
Errors and limits
Failures arrive in two places: at the transport, as an HTTP status, and inside a tool result, as an error flag with a plain-language message. Each one has a different answer.
Two layers of failure
A call can fail in two different places, and the two need different answers. Read which layer you are in before you retry anything.
- Transport
- The HTTP request itself failed. You get a status code and no tool result. This is about the connection or the credential.
- Tool result
- The request succeeded and the tool refused, or broke. You get a normal result carrying
isError: trueand a message written for a reader.
A tool error is not an HTTP error. A refused call still comes back 200, because the protocol treats the refusal as the tool’s answer.
Transport errors
- 401. No credential, or one the server will not accept. The response carries a
WWW-Authenticateheader naming the metadata document, which is the client’s cue to run the sign-in. See Authentication. - 404. The wrong path. The server is at
/api/mcp. The older server-sent-events transport is not served. - A cut connection on a slow call. Work that takes real time does not hold the request open. See long-running work below.
Tool errors
Every tool failure returns through one envelope, and the envelope separates two kinds of failure.
- A refusal
- The tool deliberately declined: a missing argument, an unknown edit or source, no access to the project, an unsupported format, a guardrail. Nothing is broken. The message says what to do.
- An unexpected error
- Something went wrong that the tool did not anticipate. This is the class worth retrying, and the class worth reporting.
Both arrive as isError: true with human-readable text. The difference is in the message: a refusal tells you what would have made the call valid, and usually names the values it will accept.
An illustration of the envelope. The envelope is what the server sends; the message inside it is an example, not a quotation.
{
"isError": true,
"content": [
{
"type": "text",
"text": "No edit named \"Teaser\". Edits in this project: Rough Cut, Sizzle."
}
]
}What to retry
This section is guidance, not a contract. The server publishes no retry policy and holds itself to none. These are the responses that follow from how it classifies a failure.
- An unexpected error — retry once. If it repeats, stop and report it. Repeating a broken call does not fix it.
- A refusal — do not retry unchanged. The same call fails the same way. Correct the argument the message names, then call again.
- An ambiguous reference — resolve it, then retry. When a source name matches several files the refusal lists the candidates and their ids. Pass an id.
- An out-of-range position — read the edit again. Segment positions move whenever the edit changes. Take them from a fresh read, never from memory.
- A 401 — sign in again. Let the client refresh. Do not retry the call with the dead token.
Long-running work
Some work — rendering a file, rating a large batch of footage, fetching frames — takes longer than one HTTP request should be held open for. Those tools accept the job and report on it rather than blocking.
The first call comes back immediately, saying the work has started and carrying a token. Call the same tool again with the same arguments plus that token to get progress, and eventually the result. The pattern is the same everywhere it appears, so a client that handles it once handles it for every tool.
The import readiness lock
A project’s media is analysed after it is imported, and a cut built against half-analysed footage is a worse cut. So the server holds work back until the first import finishes.
- Read-only tools are never held. The gate looks at the tool’s read-only annotation and lets it through. You can list sources, read transcripts and read edits while the wait plays out — the refusal itself names those tools.
- A tool that changes the project is refused. The refusal says what is still outstanding and how far the analysis has got, in the form “3 of 5 sources analysed”. It never gives an estimated time, because there is no honest one to give.
- The refusal says not to retry in a loop and not to reach for a different tool to get around it. Wait, then call again.
- Only the first import locks a project. Adding media to a project that has already imported does not block anything; the edit you build simply will not contain the footage that is still arriving.