The MCP server
The MCP server gives your agent eight tools. watch_video is the one it reaches for by default, and it covers the complete video unless you name a window. The rest cover the jobs that are a different shape: many videos at once, a finished document, the words, a live stream, your balance, and a method for a recurring job.
Last updated
The tools
Your agent picks between them from what you asked. Three of them touch no video at all, and cost nothing.
| Tool | Returns | Cost |
|---|---|---|
watch_video | The reading, in words, with the second of every moment it names. Plus the session_id for the next question about the same video. | About 2,500 tokens of context for a first look, and a few hundred for a question that carries the session_id. |
watch_videos | One answer per video, together, each with the session_id of its own video. | One reading per video, the same price as asking one by one. What it saves is the round trips and the waiting. |
run_playtool | A finished document: the same result the tool's page on tryplayhead.com produces, with its share link, embed snippet and editor link. | A few minutes of work, priced per tool. The call waits while it can and hands back a run_id with live progress. |
get_transcript | Plain text, optionally with word-level timings, plus whether the audio was speech at all. | No pictures are read, so this is the cheapest call there is. |
attach_stream | A stream id, and the address to send to when the encoder is yours. | Charged for as long as the stream is open, so stop it when the event ends. |
detach_stream | What the event saw, and what it cost. | Nothing. It ends the charge that attach_stream started. |
get_account | Which plan is connected, credits left, and what recent calls cost. | Nothing. No video is touched. |
get_playbook | A method for one recurring job: the call order, what is measurable, and where the judgement is yours. | Nothing. No video is touched. |
watch_video(url?, question?, session_id?, …)
The default, and the right answer to almost any question about what is on screen. Without a question it covers the complete video.
- string
- A link to the video, an upl_… id from an upload, or a path to a file on your own machine when the server runs over stdio. Leave it out when you pass a session_id.
- string
- What you want to know. Leave it out for what happens across the complete video. Ask for one thing and you get that one thing, faster and for less.
- string
- The handle from an earlier answer about the same video. Pass it and the next question reads what was already found instead of looking again.
- string[]
- What you already know and the video cannot show: what you are building, and what you were asked. Plain sentences. It costs almost nothing and the answer is better for it.
- number[]
- The seconds to read, [start, end], from the start of the file. Use it for a moment the first answer did not cover. Reading four seconds costs what four seconds cost, not what the video costs.
- number[]
- The part of the picture to read, [left, top, right, bottom], as fractions of the width and the height. [0.5, 0, 1, 0.5] is the top right quarter. It makes small text large enough to read.
- glance | read | full
- How many moments of the video are read. Every depth dates every second the same way, so a glance is shorter and never vaguer. Absent is full. Use glance to find out whether a video is worth reading properly: it costs about a sixth of a full reading.
- object
- A JSON Schema. Send one and the answer carries an object in that shape under the prose, so your code reads values instead of parsing sentences. A field the video cannot fill comes back in unanswered with its reason.
- string
- How the answer reads, in your words instead of ours. It changes the wording and nothing else: what was looked at and what was found stay the same. Use it for the voice, the language, and what to leave out.
- boolean
- Watch the whole video again and pay for it again. Ask without it first: the answer states the price and starts nothing.
watch_videos(urls, question?, schema?, batch_id?)
The same question about several videos: a folder of adverts, a set of webinar recordings, a week of uploads. Use it instead of calling watch_video in a loop.
- string[]
- The videos: links, upl_… ids, or paths to files on your own machine over stdio. Required to start a batch, ignored with batch_id.
- string
- What you want to know about each one. The same question goes to every video. To ask each one something different, call watch_video per video.
- object
- A JSON Schema every answer comes back in. This is what a batch is for: twenty videos read into the same fields can be stacked and compared, and twenty paragraphs are a folder.
- string[]
- What you already know that the videos cannot show. Plain sentences.
- string
- A batch to keep waiting on, from an earlier call. The call waits while it can and hands back progress if videos are still running.
run_playtool(tool, url?, prompt?, run_id?, …)
You want the product rather than an answer in the chat. sop turns a screen recording into a step-by-step guide with screenshots. prompt turns a clip into the brief to remake it with a generator.
- sop | prompt
- Which PlayTool to run.
- string
- The video to run it on: a link, an upl_… id, or a local path over stdio. Required to start a fresh run.
- string
- What you want, in your own words. For prompt: which generator you write for, and what should be different about the video. sop ignores it.
- string
- A run to keep waiting on, from an earlier call.
- string
- An existing document to redo one step of, with step. The document keeps its share link.
- string
- Which step to redo, for example "step-3". Needs sop_id beside it.
get_transcript(url, words?, language?)
The question is about what is said rather than what is shown.
- string
- The same source as watch_video.
- boolean
- Include word-level timestamps.
- string
- Name the language, for example "en". auto detects it. Name it when you already know it and the audio is mostly music or noise.
attach_stream(url?, road?, protocol?, question?, label?)
A live event rather than a recording: an HLS playlist, a camera, or your own encoder. Playhead watches it minute by minute until you stop it.
- string
- The address of the stream: an HLS playlist, an RTSP camera, or an SRT or RTMP address you own. Leave it out and pass road: push instead.
- pull | push
- pull opens an address, and is the default when you pass a url. push hands you back an address and a stream key for your own encoder to send to.
- rtmp | srt
- Which one a push event listens on. RTMP unless you asked for SRT.
- string
- What you are watching this event for. It is set once and applies to every minute.
- string
- A name for this event, for your dashboard.
detach_stream(stream_id)
The live event has ended. Nothing stops on its own.
- string
- The event id, from attach_stream.
get_account(history?, limit?)
Before an expensive pass over something long, or when a call was refused for want of credit.
- boolean
- Include recent jobs and what they cost.
- number
- How many recent jobs to list. Default 10.
get_playbook(task, section?)
A job with a known shape, such as an ad teardown, a caption audit or a render check, rather than a one-off question.
- enum
- Which playbook.
- string
- One section of it, fetched only when you ask for it.
How much comes back at once
This is a property of MCP clients rather than of Playhead, and it is the single most common surprise when building on the server.
An MCP client caps one tool result, and a result over that cap is dropped whole rather than shortened. Every answer here is words, a few kilobytes at most, so no call comes near it.
In practice this costs you nothing. An answer in words is a few kilobytes whatever the video is, so one call covers a two hour recording as easily as a fifty second advert.
Sessions covers what a second question costs, which is the number to plan around.
Running it yourself
The npm package is MIT. It calls the hosted API, so a key or a token still pays for the work.
claude mcp add --transport http playhead https://mcp.tryplayhead.com/mcpnpx -y @playhead/mcp
# or, with Claude Code:
claude mcp add playhead -e PLAYHEAD_API_KEY=sk_live_… -- npx -y @playhead/mcp{
"mcpServers": {
"playhead": {
"command": "npx",
"args": ["-y", "@playhead/mcp"],
"env": {
"PLAYHEAD_API_URL": "https://api.tryplayhead.com",
"PLAYHEAD_API_KEY": "sk_live_…"
}
}
}
}Configuration
Environment variables read by the npm package. CLI flags --api-url, --api-key, --http and --port override them.
| Variable | Default | Purpose |
|---|---|---|
PLAYHEAD_API_URL | https://api.tryplayhead.com | REST API base URL. |
PLAYHEAD_API_KEY | not set | Your API key. On the remote transport the sign-in wins over it. |
PLAYHEAD_MCP_CACHE_DIR | ~/.cache/playhead | Where answers are kept on your disk, for 7 days. A repeated question is free. |
PLAYHEAD_MCP_IMAGE_DELIVERY | auto | auto, same-turn or next-turn. Some clients show an attachment one turn late, and this settles it. |
MCP_TRANSPORT | stdio | stdio or http. |
PLAYHEAD_MCP_REQUIRE_AUTH | false | Reject unauthenticated remote calls. |
PLAYHEAD_MCP_MAX_RESULT_BYTES | 950000 | The largest tool result to send. Too low and you lose part of an answer. Above your client's own cap and you lose all of it. |
Questions
- What is an MCP server?
- Model Context Protocol is a standard way to give an AI agent tools it can call. An MCP server publishes a set of tools with typed arguments, and your agent decides when to call them from what you asked. Playhead publishes eight.
- How much of my context does one answer take?
- About 2,500 tokens for a first look at a video, and a few hundred for a question that carries the session id. The answer is words, so it does not grow with the length of the video. A two hour recording answers in about as much text as a thirty second advert.
- Do I choose how closely Playhead looks?
- Only if you want to. Ask a question and you get an answer. depth is there when you want to spend less: glance reads fewer moments of the video and costs about a sixth of a full reading, which is the cheap way to find out whether a video is worth reading properly.
- Can I get the answer as JSON instead of prose?
- Yes. Send a JSON Schema as schema and the answer carries an object in that shape beside the words, so your code reads values instead of parsing sentences. A field the video cannot fill comes back in unanswered with the reason.
- Can I run the MCP server myself?
- Yes. npx -y @playhead/mcp runs it over stdio, and --http --port=8787 runs the HTTP transport. Both call the hosted API, so an API key or an OAuth token is still what pays for the work.