Developer docs
Search travel footage from your product.
Two ways in, one library. Give an AI model the MCP server and it searches by itself, or call the REST API from your backend.
Before you start
There's no key or sign-in during early access, so both addresses work straight away. Every search is read by AI before it runs, so it takes two to five seconds and understands places, kinds of shot and what to leave out, in any language.
https://api.studio.tbo.com/mcphttps://api.studio.tbo.com/api/v1/searchMCP server
The MCP server gives an AI model two tools. The model reads their descriptions when it connects and decides by itself when to search. It speaks Streamable HTTP without sessions, so every call is a single request.
Tools
library
What the library covers
Lists the countries, the places with the most footage and the common activities, with how many videos and hours the library holds. Assistants call it when they aren't sure a place is covered.
Takes no input.
search
Search travel footage
Finds footage from a plain description, best match first. It reads places, kinds of shot, time of day, what to leave out and how many results you want from the words themselves.
- querytext, required
- What to find, in any language. “Aerial shots of the Maasai Mara at sunset, no text on screen”.
- limitnumber, optional
- How many results to return, from 1 to 25. Ten if left out.
Both tools only read. They say so in their annotations, so assistants run them without asking the person each time.
Connect from code
Most model providers can use an MCP server directly. The lit lines are the ones that connect the model to the library.
Claude API
Claude connects to the server for you. Name the server once, and switch its tools on with a matching toolset.
import Anthropic from "@anthropic-ai/sdk"; const TBO_MCP = "https://api.studio.tbo.com/mcp";const client = new Anthropic(); const response = await client.beta.messages.create({ model: "claude-opus-5-5", max_tokens: 4096, betas: ["mcp-client-2025-11-20"], mcp_servers: [{ type: "url", url: TBO_MCP, name: "tbo-studios" }], tools: [{ type: "mcp_toolset", mcp_server_name: "tbo-studios" }], messages: [{ role: "user", content: "Show me a morning in the Masai Mara" }],});OpenAI Responses API
OpenAI's servers call ours. Read-only tools are safe to run without asking for approval each time.
import OpenAI from "openai"; const TBO_MCP = "https://api.studio.tbo.com/mcp";const client = new OpenAI(); const response = await client.responses.create({ model: "gpt-5", tools: [{ type: "mcp", server_label: "tbo-studios", server_url: TBO_MCP, require_approval: "never", }], input: "Show me a morning in the Masai Mara",}); console.log(response.output_text);Gemini, or any model, with the MCP library
Your code connects to the server and hands its tools to the model. This runs where your code runs, so it also works with a server on your own computer.
import { GoogleGenAI, mcpToTool } from "@google/genai";import { Client } from "@modelcontextprotocol/sdk/client/index.js";import { StreamableHTTPClientTransport,} from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const TBO_MCP = "https://api.studio.tbo.com/mcp"; const mcp = new Client({ name: "my-chatbot", version: "1.0.0" });await mcp.connect(new StreamableHTTPClientTransport(new URL(TBO_MCP))); const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });const response = await ai.models.generateContent({ model: "gemini-3.6-flash", contents: "Show me a morning in the Masai Mara", config: { tools: [mcpToTool(mcp)] },}); console.log(response.text);Plain HTTP, from any language
Every call is one POST with a small JSON body. There's no session to open first, so a single request is enough.
curl -s https://api.studio.tbo.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": "search",
"arguments": {"query": "elephants at a waterhole", "limit": 3}}}'What search returns
Every answer comes twice: as text the model reads and repeats, and as structured data for your code. Each result is a chapter of a video, with the scenes in it that match. This is a real answer to “lions at sunrise”, shortened to one result.
Search: "lions at sunrise"
Understood as: Looking for lions at sunrise. Filters: golden hour.
Found 2 matching chapters. Showing 2, best first.
1. Wildlife safari at Mara Porini Camp
Mara Porini Camp, Narok, Kenya · 50 s · from "MARA PORINI"
Footage showcases a variety of African wildlife including hyenas, wildebeest, warthogs, jackals, vultures, zebras, giraffes, elephants, and lions. Tourists enjoy a game drive in a safari vehicle, spotting and photographing animals across the open savanna at sunset.
Video: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=0,50.1
Thumbnail: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg
Scenes:
- 0:24 to 0:27 (wide): A male lion with a dark mane walks along a rocky riverbank at golden hour, with rushing water and a vehicle roof edge visible.
Video: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=24.2,27.2 · Thumbnail: https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg{
"query": "lions at sunrise",
"understoodAs": "Looking for lions at sunrise. Filters: golden hour.",
"status": "found",
"total": 2,
"notices": [],
"results": [
{
"id": "chp_01M75H7ZDRJZZ7H4HG5V9M16RX_000",
"title": "Wildlife safari at Mara Porini Camp",
"url": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=0,50.1",
"description": "Footage showcases a variety of African wildlife…",
"place": "Mara Porini Camp",
"state": "Narok",
"country": "Kenya",
"countryCode": "KE",
"locationMatch": "certain",
"startSec": 0,
"endSec": 50.4,
"durationSec": 50.4,
"thumbnailUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg",
"videoUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=0,50.1",
"sourceVideo": { "id": "ast_01M75H7ZDRJZZ7H4HG5V9M16RX", "name": "MARA PORINI" },
"shareWithoutTextOrLogo": 0.93,
"score": 0.759,
"scenes": [
{
"id": "scn_01M75H7ZDRJZZ7H4HG5V9M16RX_0014",
"description": "A male lion with a dark mane walks along a rocky riverbank at golden hour, with rushing water and a vehicle roof edge visible.",
"startSec": 24.2,
"endSec": 27.5,
"durationSec": 3.3,
"thumbnailUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/thumbs/0015.jpg",
"videoUrl": "https://api.studio.tbo.com/m/ast_01M75H7ZDRJZZ7H4HG5V9M16RX/video.mp4#t=24.2,27.2",
"shotType": "wide",
"timeOfDay": "golden_hour",
"people": null,
"textOrLogoOnScreen": false,
"matchesSearch": true
}
]
}
],
"closest": [],
"closestKind": null
}| title, description | What the chapter shows, written from the footage itself. |
|---|---|
| place, state, country | Where it was filmed, when that's on record. |
| locationMatch | When you named a place: certain, right country with the state unknown, or location unknown. |
| startSec, endSec, durationSec | Where the chapter sits in its source video, and how long it runs. |
| thumbnailUrl | A still from the chapter. |
| videoUrl | A link that plays only this chapter of the 480p preview. |
| sourceVideo | The id and name of the video it comes from. |
| shareWithoutTextOrLogo | How much of the chapter is free of added titles and logos, from 0 to 1. |
| scenes | Up to three scenes that match, each with its own description, times, thumbnail, video link, shot type, time of day and how many people are in it. |
| understoodAs | How the search was read, so the assistant can confirm it with you. |
|---|---|
| status, total | Whether anything matched, and how many chapters did in all. |
| notices | Anything worth passing on, such as a filter that was dropped to find something. |
| closest | Only when nothing matched: the nearest footage the library has. It's never a match, and assistants are told so. |
How links behave
They play the right moment
A scene link opens the preview at the scene's first second and pauses at its last, in any browser.
They don't expire
Each link asks our server for a fresh copy when it's opened, so a link in an old chat still works next month.
They're previews
Links open the 480p copy of the footage. The original files are never linked.
Chats show them as links
Claude and ChatGPT don't draw pictures from tool results into the chat, so thumbnails arrive as links you can open.
REST API
One endpoint searches the library. Send a POST with JSON, and get back ranked chapters of video with the scenes that match. Use it from a backend, a website or a data pipeline, wherever no AI model is choosing the searches for you.
Request
curl -s https://api.studio.tbo.com/api/v1/search \
-H "Content-Type: application/json" \
-d '{"text": "lion walking in the Maasai Mara", "limit": 1}'| text | What to find, in plain words and any language. Places, kinds of shot, time of day and what to leave out are read from the words. |
|---|---|
| limit | How many results a page holds, from 1 to 50. Twelve if left out. |
| offset | How many results to skip, for the next page. |
| previous | The query object of the last answer, sent with a follow-up such as “only aerial shots”. The follow-up then adjusts that search instead of starting a new one. |
Response
A real answer, shortened to one result and the fields most apps use. Stills and previews come back as paths, such as /files/media/…, so put the API address in front of them. To play one scene of a preview, add its times in seconds to the link, as in #t=102.2,105.
{
"searchId": "srch_01M77MJWV3NQNPR77HXNNVYFCR",
"status": "ok",
"total": 38,
"query": {
"subject": "lion walking",
"countries": [{ "code": "KE", "name": "Kenya" }],
"places": ["Maasai Mara"],
"interpretation": "Looking for lion walking in the Maasai Mara. Only from Kenya."
},
"notices": [],
"results": [
{
"id": "chp_01M75H48116D2AXQ7YV6T9Y46F_002",
"title": "Sounds of the Wild",
"summary": "Observing lions, leopards, and evening campfires under the starry African sky.",
"startMs": 72683,
"endMs": 105041,
"place": "Maasai Mara",
"state": "Narok",
"country": "Kenya",
"locationMatch": "certain",
"cleanShare": 1,
"thumbnailUrl": "/files/media/ast_01M75H48116D2AXQ7YV6T9Y46F/thumbs/0061.jpg",
"asset": {
"id": "ast_01M75H48116D2AXQ7YV6T9Y46F",
"name": "AFRICA ECO WILDERNESS",
"proxyUrl": "/files/media/ast_01M75H48116D2AXQ7YV6T9Y46F/proxy.mp4"
},
"score": { "meaning": 0.806, "words": 0.04, "name": 0.06, "quality": 0.029, "total": 0.935 },
"scenes": [
{
"id": "scn_01M75H48116D2AXQ7YV6T9Y46F_0060",
"startMs": 102248,
"endMs": 105041,
"description": "A large male lion walks directly toward the camera along a grassy dirt path during the early morning light.",
"thumbnailUrl": "/files/media/ast_01M75H48116D2AXQ7YV6T9Y46F/thumbs/0061.jpg",
"shotType": "medium",
"timeOfDay": "day",
"people": "none",
"clean": true,
"matches": true
}
],
"moreScenes": 15
}
],
"closest": [],
"tookMs": 1682
}| status, total | ok when something matched, empty when nothing did, and how many chapters matched in all. |
|---|---|
| query | How the text was understood: the subject, countries, named places and filters. interpretation says it in one sentence. |
| notices | Things worth showing the person, such as a filter that was dropped to find something. |
| results[] | Chapters of video, best first. A chapter is a stretch of one video about one place or subject. |
| title, summary | What the chapter shows, written from the footage itself. |
| startMs, endMs | Where the chapter sits in its source video, in milliseconds. |
| place, state, country | Where it was filmed, when that's on record. locationMatch says how sure that is. |
| cleanShare | How much of the chapter is free of added titles and logos, from 0 to 1. |
| thumbnailUrl, asset.proxyUrl | A still and the 480p preview of the whole video. Both are paths: put the API address in front of them. |
| scenes[] | The chapter's scenes that pass the search, best first, each with its times, description, still, shot type, time of day and whether people are in it. matches is true when the scene itself matches. |
| closest | Only when nothing matched: the nearest footage the library has. It's never a match. |
Good to know
- Do I need an account or a key?
- Not during early access. The MCP server and the API are open while sign-in is built. Assistants will be asked to sign in once when keys arrive.
- What does the library cover?
- Ask your assistant “what does the TBO Studios library cover?”. The library tool answers from the live library, so the list is always current.
- How fast is a search?
- Usually two to five seconds, because each search is read by AI before it runs. Assistants often run two or three searches for one request.
- What happens when nothing matches?
- The answer says so plainly. When the library has something close, it's listed separately and marked as not a match.
- Can I get the full-quality files?
- Not through these links, which play 480p previews. Licensed downloads come with accounts. Tell us what you need through early access.
- Who wrote the descriptions?
- AI, from watching the footage. They're usually right about what's in the picture, and they can be wrong about names and places.
- Are searches recorded?
- Yes. The words of every search are kept so we can see what people look for and what the library is missing. Please don't put personal details in a search.