Gemini-Video-MCP
This server gives Claude/AI clients the ability to have Gemini natively watch videos and describe them, plus several helper tools for handling media files.
describe_video — Send a local video (mp4, mov, webm, gif, etc.) to Gemini for a detailed, timestamped Chinese description of on-screen action and audio; supports custom
prompt,persona,hint,low_resolutioncost-saving, static/agentic processing modes, and close-up slices viastart/end/fps.describe_video_url — Same pipeline for a direct video-file link (downloaded to a temp folder then deleted) and for YouTube video-page links (watch/shorts/youtu.be), which are read directly by Gemini without downloading.
view_media — Return an image, or a single frame extracted from a video, as actual image content so the calling model can see it; supports
timestampfor frame selection andmax_dimensionfor downscaling.estimate_cost — Approximate how many input tokens a local video will cost (uses ffprobe when available, otherwise file-size based).
get_upload_url — Return the HTTP upload endpoint so a claude.ai sandbox can push chat-uploaded files to the server for later description; in local stdio mode it reports that the endpoint isn't needed.
Operational extras — HTTP mode for remote claude.ai connectors (secret-protected), an upload endpoint with file sanitization/auto-pruning, upload caching by file hash, and automatic fallback/retry behavior for model/thinking-level mismatches.
Allows describing video content using Google's Gemini model, including extracting timestamps and analysis of visual and audio tracks.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Gemini-Video-MCPDescribe the video at ~/Downloads/sample.mp4"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
English | 简体中文
Gemini-Video-MCP
An MCP server that hands local video files to Gemini's native video understanding and returns a detailed, timestamped description of what's happening on screen and in the audio track. The video pipeline was extracted and cleaned up from a larger Discord/QQ bot project (MoFox-Bot) where it had already been battle-tested.
Gemini is really good at describing video — good enough that it tends to get dramatic and lyrical
about it. The default prompt in this server deliberately leaves that flourish in (it doesn't ask
for dry, objective summaries) and asks Gemini to write the description in Chinese. If you want a
flatter tone or a different output language, pass your own prompt.
Tools at a glance
describe_video— the main tool: local video → text description.Supports common containers:
mp4 / mov / webm / avi / mkv / flv / wmv / mpeg / mpg / m4v / 3gp / 3gpp;Also handles
.gifnatively (sent as rawimage/gif, so Gemini perceives the full animation instead of a single extracted frame);Small videos (≤14MB) go inline in a single request; larger ones automatically go through the Files API (upload → wait until ready → describe → delete the remote copy when done), up to a 2GB per-file limit;
low_resolutionis a cost-saving switch;personalets Gemini narrate in character;hintlets you feed in what a human already thinks the video is about, useful for abstract or meme-y content (the model is instructed to still describe what it actually sees, not just agree with you);promptfully overrides the built-in template.
describe_video_url— downloads a video from a direct link and runs it through the same pipeline (downloaded to a temp folder, deleted right after).Same parameters as
describe_video, justpathbecomesurl;Only works with direct video file links (something that resolves straight to a video file, ending in
.mp4/.mov/.webm/etc.). Platform watch pages (YouTube, TikTok, Bilibili, etc.) are not direct links and won't resolve — that would need something like yt-dlp, which is out of scope for now;500MB per-file cap; 15s connect / 300s total timeout; non-video pages, non-2xx responses, and oversized files all get a readable error.
view_media— returns a picture (either an image file, or one frame pulled from a video) as actual image content, so the calling model (Claude, etc.) can look at it directly — as opposed todescribe_video, which has Gemini watch the video and write text about it.Images (
png/jpg/jpeg/webp/gif): returned as-is, downscaled (never upscaled) if the longer side exceedsmax_dimension(default 1024, adjustable 16–4096). GIFs return only their first frame (usedescribe_videoif you want the full animation understood);Videos: pass
timestamp(in seconds) to grab that frame, or omit it to grab the frame at the midpoint; requires ffmpeg on the host machine (a clear error is returned if it's missing).
estimate_cost— a small helper that estimates roughly how many input tokens a video will cost before you send it (usesffprobefor real duration when available, otherwise estimates from file size).get_upload_url— a small helper that returns the upload endpoint URL so a claude.ai sandbox can push a chat-uploaded file to this server before describing it (see "HTTP mode" below). Under local stdio mode there is no upload endpoint, so calling this just returns "not needed — you're on the same machine, pass the local path directly."
Related MCP server: local-video-scenes-mcp
Installation
You'll need uv for dependency management, Python ≥3.11 (uv will
resolve this automatically from pyproject.toml), and ffmpeg / ffprobe on your PATH (used by
view_media for frame extraction/scaling and by estimate_cost for reading duration — describe_video
and describe_video_url don't need them; missing ffmpeg only breaks the first two, with a clear error
message).
cd /path/to/Gemini_Video_MCP
uv venv
uv pip install -e .Configure the API key
Copy .env.example to .env and fill in your key (free to get at
Google AI Studio):
GEMINI_API_KEY=your-key-here
GEMINI_MODEL=gemini-3.5-flashYou can also skip .env entirely and inject the key at registration time with -e GEMINI_API_KEY=...
(see below). If both are present, the environment variable wins; .env is only a fallback.
Environment variables
Variable | Required? | Default | Notes |
| Yes | — | Your Gemini API key |
| No |
| Model identifier |
| No |
| API base URL; only change this if you're proxying |
| No |
| One of |
| No | empty (falls back to | Model used for agentic mode; only needed when the main model doesn't support it |
| Only for | — | The sole access lock for HTTP mode; server refuses to start without a real value |
| No | none (falls back to | Public URL after tunneling; used by |
(All values above are placeholders — fill in your own and never commit .env; it's already in
.gitignore.)
Running locally (for debugging)
uv run python main.py # starts in stdio mode (normally launched by your Claude client, no need to run this by hand)Registering with Claude Code
Run this from inside the project directory (passing the key via -e):
claude mcp add gemini-video -e GEMINI_API_KEY=your-key-here -- uv run --directory /path/to/Gemini_Video_MCP python main.pyIf you've already set up .env, you can drop the -e:
claude mcp add gemini-video -- uv run --directory /path/to/Gemini_Video_MCP python main.pyVerify it registered:
claude mcp listRegistering with Claude Desktop
Edit Claude Desktop's config file (Windows: %APPDATA%\Claude\claude_desktop_config.json) and add
this under mcpServers:
{
"mcpServers": {
"gemini-video": {
"command": "uv",
"args": [
"--directory",
"D:/path/to/Gemini_Video_MCP",
"run",
"python",
"main.py"
],
"env": {
"GEMINI_API_KEY": "your-key-here"
}
}
}
}Claude Desktop can't hand a chat-uploaded video straight to an MCP tool. To have Claude read a video from your machine, just type out the video's full file path in the conversation (e.g.
D:/videos/cat.mp4).
HTTP mode (for claude.ai / mobile remote use)
The default stdio mode can only be launched by a Claude client running on the same machine. If you want claude.ai's web app or mobile app to use this video tool too, you need HTTP mode: the server opens a port locally, you expose that port to the internet, and then you add it in claude.ai as a Custom Connector.
The short version: HTTP mode serves on local port 8768; a tunnel (e.g. Cloudflare Tunnel) exposes that port to the internet; the secret baked into the URL path is the only lock on the door — without it, nobody gets in.
Step 1: set an access secret
The secret gets embedded in the URL path (/mcp/<secret>), and it's the only thing standing between
this port and the public internet, so it needs to be long and random.
Generate a random secret (run this from a terminal in the project directory):
uv run python -c "import secrets; print(secrets.token_urlsafe(32))"Paste the output into this line in your
.env(copy.env.examplefirst if you don't have one yet):GEMINI_MCP_HTTP_SECRET=paste-the-generated-string-hereNever share this secret or screenshot it — leaking it is the same as handing someone the front door key. If it's left blank or still a placeholder, the server will refuse to start with
--http(this is intentional, so it never goes online unprotected).
Step 2: start the HTTP server
Double-click start_http.bat in the project directory (or run uv run python main.py --http in a
terminal). Once it's up, the local address is:
http://localhost:8768/mcp/<your-secret>Keep that terminal window open — closing it stops the server.
Step 3: expose it to the internet with a tunnel (Cloudflare Tunnel recommended)
If you already have a tunnel set up for other local services, you can reuse it — just point a new
public hostname at http://localhost:8768. Using Cloudflare Tunnel as an example:
Open the Cloudflare Zero Trust dashboard → Networks → Tunnels → select your tunnel → Configure.
On the Public Hostname tab, click Add a public hostname:
Subdomain: pick something like
gemini-video; Domain: your own domain (the final address will begemini-video.yourdomain.com).Service → Type:
HTTP, URL:http://localhost:8768(note: http, localhost, port 8768).
Save and wait a minute or two for DNS to propagate.
Just want to try it once, without touching the dashboard? Run a throwaway command (the address changes every time, so it's not for long-term use):
cloudflared tunnel --url http://localhost:8768It prints a
https://random-name.trycloudflare.comaddress you can use once and discard.(Alternative: if you'd rather use Tailscale instead of Cloudflare, the equivalent is
tailscale funnel 8768, which gives you ahttps://<machine-name>.<tailnet>.ts.netpublic address — append/mcp/<secret>the same way.)
Step 4: add it as a Custom Connector in claude.ai
Open claude.ai → avatar → Settings → Connectors.
Click Add custom connector.
Name: anything you like, e.g.
Gemini Video.Remote MCP server URL: your public address plus the secret path:
https://gemini-video.yourdomain.com/mcp/<your-secret>(swap in whatever domain you set up in Step 3, and the secret you generated in Step 1.)
Save. Claude should connect and list all five tools —
describe_video/describe_video_url/view_media/estimate_cost/get_upload_url— which means it worked.
From then on you can ask Claude to describe videos right from claude.ai. Note that in remote mode, Claude reads file paths on the server machine, not files on your phone.
Custom Connectors typically require a paid Claude plan (Pro/Max/etc.); the exact menu wording may vary by app version.
Letting the claude.ai sandbox push files to your machine (upload endpoint)
In remote mode, describe_video still only reads paths on the server machine — files uploaded in
a claude.ai chat or downloaded inside its sandbox can't reach your machine on their own. That's what
the --http mode's extra upload endpoint is for:
POST http://localhost:8768/upload/<your-secret>It reuses the same GEMINI_MCP_HTTP_SECRET (a wrong secret in the path just 404s). Have claude.ai's
sandbox run a snippet that POSTs the file it has as multipart form data (swap in your tunnel domain
and secret):
import requests
# The sandbox already has a file (chat-uploaded, or downloaded/generated by the sandbox itself), e.g. /tmp/clip.mp4
resp = requests.post(
"https://gemini-video.yourdomain.com/upload/<secret>",
files={"file": open("/tmp/clip.mp4", "rb")},
)
print(resp.json())
# -> {"saved_path": "/path/to/Gemini_Video_MCP/temp_media/20260714_..._clip.mp4", "size_mb": 3.2, "hint": "pass saved_path to describe_video"}Once you have saved_path, just have Claude call describe_video (or view_media) with it.
You don't need to explain any of this to Claude by hand: the server ships a
get_upload_urltool plus server-level instructions, so Claude in claude.ai will automatically callget_upload_urlwhen it sees a chat-uploaded file, POST it from the sandbox, and use the returnedsaved_path. You just upload a video and say "take a look at this." Prerequisites:GEMINI_MCP_PUBLIC_BASE_URL(your public domain) is set in.env, and the claude.ai sandbox has outbound internet access. Note thatget_upload_url's response contains the full secret (that's what lets the sandbox POST), so it will show up in that conversation — if that bothers you, discard that chat afterward or rotate the secret periodically.
Constraints: 500MB per file; filenames are sanitized (to prevent path traversal) and prefixed with a
timestamp (to prevent overwrites); the caller can never choose a storage path — everything lands in
the server's own temp_media/ directory (auto-pruned, oldest first, once the directory exceeds 2GB
total). The stdio/local mode does not expose this endpoint.
Example usage (in conversation)
"Describe the video at
D:/videos/monkey.mp4for me" → triggersdescribe_video."Narrate
D:/videos/dance.mp4like a snarky high schooler" → Claude passes apersona."This video is people playing five-in-a-row with eggs, describe
D:/videos/eggs.mp4" → Claude puts your description intohintso the model can make sense of something abstract or meme-y."Describe this direct video link:
https://example.com/clip.mp4" → triggersdescribe_video_url(downloads, then describes)."Show me what
D:/videos/monkey.mp4looks like at the 8-second mark" → triggersview_media(pulls the frame at 8s for Claude to actually look at)."Take a look at this picture,
D:/pics/meme.png" → triggersview_media(feeds the image straight to Claude)."About how many tokens would it cost to describe
D:/videos/long.mp4?" → triggersestimate_cost.Want to save money on a long video? Have Claude set
low_resolution=True.
Processing modes (static / agentic) and close-ups
Both describe_video and describe_video_url accept a mode argument:
| What it does | When to use |
| agentic when the video is ≥ 5 minutes, static otherwise (static whenever the duration can't be read) | The set-and-forget choice |
|
| Short clips, or when you want every second described |
| Interactions API — the model decides which stretches to look at, at what frame rate, and whether to listen to the audio | Hunting for something inside a long video; saves a lot of media tokens |
Agentic requires the video to live in the Files API (small local files get uploaded once too). If it
can't run, the server falls back to static and says why in the footer. When the main model doesn't
support agentic, point GEMINI_AGENTIC_MODEL at one that does; static keeps using GEMINI_MODEL.
Don't use agentic on short clips: a 92-second video measured ~13k tokens on static versus ~85k on
agentic — it re-reads frames and pulls the audio track repeatedly.
Close-ups: describe_video also accepts start / end / fps, feeding the model only that
slice (always static in this mode).
Times can be seconds (
39) orm:ss(1:06); with onlystart, it looks 30 seconds ahead;fpsdefaults to 1 and is capped at 10;If
hintreads like a question (ends with a question mark or contains a question word), the model answers that question about the slice; otherwise it walks through the slice second by second, covering actions, sounds and on-screen text;Timestamps in the answer still refer to the original video's timeline.
Upload cache: videos that go through the Files API are recorded in
temp_media/upload_cache.json keyed by content sha256, so re-describing the same file within 48
hours reuses the remote file instead of uploading it again (the entry is validated against the Files
API before reuse and re-uploaded if stale). Watching a video once and then zooming into a few
seconds therefore costs a single upload.
The usage line at the end of the returned text names the processing that actually ran
(处理:static / agentic(模型 …) / static(细看 39s–46s,fps=5)).
Cost notes
Gemini charges input tokens by video duration:
Mode | Rate | 1-minute video | Notes |
Standard (default) | ~300 tokens/sec | ~18k input tokens | More visual detail |
Low-res ( | ~100 tokens/sec | ~6k input tokens | Cheaper for long videos, coarser detail |
These figures are input tokens only; output tokens are billed separately depending on how long the
description ends up being. Run estimate_cost before sending a large video if you want to know what
you're in for.
The thinking-token gotcha (already mitigated)
Gemini 3.5's "thinking" tokens also count against maxOutputTokens. If the output budget is too small,
or the thinking level too high, thinking can crowd out the visible output entirely and truncate the
description.
This server defaults to thinking_level=high (empirically, more thinking produces noticeably better
prose) and correspondingly defaults max_output_tokens to 8192 to leave room for it; if truncation is
detected, a note is appended to the result. To save money, set GEMINI_THINKING_LEVEL=minimal in
.env (thinking tokens are billed as output tokens). If the model doesn't support the configured
thinking level, the server automatically retries once at low.
Known limitations
.mkvisn't on Gemini's officially supported list; this server sends it asvideo/x-matroskaon a best-effort basis. If it gets rejected, convert tomp4first.Files API cap is 2GB per file; trim or compress anything larger.
Official video duration limits: roughly 1 hour at standard resolution, roughly 3 hours at low resolution (
low_resolution=True); split up anything longer.If you swap
GEMINI_MODELfor a Gemini 2.5-series model: 2.5 usesthinkingBudgetinstead ofthinkingLevel, and thethinkingLevelthis server sends by default may get rejected with a 400. The default 3.5-flash doesn't have this issue.estimate_costfalls back to a rough size-based duration estimate whenffprobeisn't available, which can be noticeably off (the result says so).view_mediadepends on ffmpeg on the host machine (frame extraction/scaling; tested against ffmpeg 8.0); a clear error is returned if it's missing. GIFs only return their first frame — usedescribe_videoto have the full animation understood.describe_video_urlonly supports direct video file links, not platform watch pages (YouTube/TikTok/Bilibili/etc.); 500MB per file, 15s connect / 300s total timeout. When called remotely from claude.ai, download time stacks on top of the tunnel's own proxy timeout (e.g. ~100s for Cloudflare), so large files are more likely to get cut off — for large files, prefer the upload endpoint to push the file to the server first, then describe it via the local path.The upload endpoint (
POST /upload/<secret>) only exists in--httpmode; 500MB per file, 2GB total fortemp_media/(oldest files pruned first once that's exceeded).Transport: stdio (local) by default;
--httpis an optional remote mode (see "HTTP mode" above).The ~100-second Cloudflare proxy timeout (524) in HTTP mode: Cloudflare's proxy cuts off any single request that goes unanswered for about 100 seconds, returning a 524. Small videos going inline are usually fine (15–60s); large videos routed through the Files API can take several minutes and are easily cut off when called remotely from claude.ai. For large files, local stdio mode (Claude Code / Desktop) is still the way to go — that path doesn't have this timeout at all.
License
MIT — do whatever you want with it, no warranty implied.
Available Tools
5 toolsdescribe_videoA
把本地视频交给 Gemini 直传识别,返回按时间轴分段的详细内容描述(画面 + 音轨)。
支持 mp4/mov/webm/avi/mkv 等常见视频格式,也直接支持 .gif(以原格式感知完整动画,不抽帧)。
Args: path: 本地视频文件的路径(建议用完整绝对路径)。 prompt: 自定义提示词。传了就【完全覆盖】默认模板(此时 persona/hint 参数被忽略)。 不传则使用内置的“翻译给纯文字 LLM 看”的详细描述模板。 persona: 可选的人设。传了会在默认提示词开头附体一行“你的人设是:…”, 让 Gemini 以该人格来解说视频。仅在未提供 prompt 时生效。 hint: 可选的前置线索——人类观看者对这个视频的形容或背景信息 (如“这是在用鸡蛋下五子棋”“声音对应表情包”)。会注入默认模板, 帮助模型理解抽象、玩梗类内容;同时要求模型以实际所见为准、不迎合虚构。 仅在未提供 prompt 时生效。 low_resolution: 低清模式。开启后约 100 token/秒(标清约 300 token/秒),长视频省钱, 但画面细节会变粗。默认关闭。 max_output_tokens: 最大输出 token 数,默认 30000。内部有 2048 的下限保护 (Gemini 的“思考”token 也计入这里;默认思考等级为 high,思考会占用 数千 token,太小会把正文挤没。思考等级可用环境变量 GEMINI_THINKING_LEVEL 调整)。
Returns: Gemini 生成的视频内容描述文本(末尾可能带用量统计或截断提示)。
| Name | Required | Description | Default |
|---|---|---|---|
| hint | No | ||
| path | Yes | ||
| prompt | No | ||
| persona | No | ||
| low_resolution | No | ||
| max_output_tokens | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses the upload to Gemini, conditional parameter interactions (prompt overrides persona/hint), internal token counting (thinking tokens count toward max_output_tokens), low_resolution speed tradeoffs, and return-value caveats (usage stats/truncation). This is very transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then organized into Args and Returns sections. Though lengthy, every sentence adds value—format support, parameter semantics, conditional overrides, and token behavior—without redundancy. It is efficiently structured for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema, but the Returns section clearly describes the output. All parameter interactions, edge cases (e.g., 2048 token floor, thinking token consumption, environment variable), and behavioral notes (e.g., .gif not frame-sampled) are covered. The complexity is fully addressed; no gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description explains all 6 parameters in detail: path (absolute path recommendation), prompt (overrides defaults and ignores persona/hint), persona (appends to default prompt only when prompt absent), hint (injects background context into default template), low_resolution (token rate tradeoff), and max_output_tokens (default, floor, thinking token interaction). This fully compensates for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: '把本地视频交给 Gemini 直传识别,返回按时间轴分段的详细内容描述(画面 + 音轨)'. It clearly states what the tool does (describes local videos via direct upload to Gemini) and distinguishes itself from the sibling 'describe_video_url' by emphasizing local file paths and direct upload.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context on when to use: for local video files with supported formats (mp4/mov/webm/avi/mkv) and .gif. However, it does not explicitly mention when not to use it or name alternatives like describe_video_url, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_video_urlA
从【网络直链】下载、或从【YouTube 视频页】云端直读视频再交给 Gemini 识别,返回按时间轴分段的中文描述。
两种输入都支持:
视频文件直链(以 .mp4/.mov/.webm 等结尾、点开就是视频本体):下载到服务器 temp_media/ 临时目录, 识别完就删掉。
✅ YouTube 视频页链接(youtube.com/watch、youtu.be 短链、shorts 等)可以直接传,服务器不下载、 由 Gemini 云端直读;仅支持公开视频(私享/会员/年龄限制的不行),免费层每天有 YouTube 总时长限额, 长视频照常按秒计费。
⚠️ B站/抖音/TikTok 等其他平台页面仍不支持(那需要 yt-dlp 之类工具,本服务器暂不支持)。 若给的是这类平台页面链接、或链接打开是网页而非视频文件,会明确报错。
其余参数(prompt/persona/hint/low_resolution/max_output_tokens)含义与 describe_video 完全一致。
Args: url: 视频文件的 http/https 直链,或 YouTube 视频页链接(youtube.com/watch、youtu.be、shorts)。 prompt: 自定义提示词,传了就完全覆盖默认模板(此时 persona/hint 被忽略)。 persona: 可选人设,仅在未传 prompt 时生效。 hint: 可选前置线索,仅在未传 prompt 时生效。 low_resolution: 低清省钱开关,默认关闭。 max_output_tokens: 最大输出 token,默认 30000(内部有 2048 下限保护)。
Returns: Gemini 生成的视频描述文本(末尾可能带用量统计或截断提示)。
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| hint | No | ||
| prompt | No | ||
| persona | No | ||
| low_resolution | No | ||
| max_output_tokens | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behaviors: temporary download to temp_media/ with deletion, YouTube cloud-read without download, public-only restriction, daily quota limits, per-second billing, unsupported platform errors, parameter precedence (prompt overrides persona/hint), and output characteristics. This is comprehensive beyond minimal expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with an overview, bullet points, warning, parameter references, and returns. It is somewhat lengthy but every part adds necessary detail for a complex tool. The redundancy of listing parameters after saying they match describe_video is minor and acceptable for self-containment.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and 6 parameters, the description is highly complete: it covers input formats, limitations, side effects, error cases, parameter dependencies, and return value format (with usage stats/truncation hints). No critical context is missing for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 0% schema_description_coverage, the description thoroughly explains every parameter: url supplies type specifications, prompt/persona/hint precedence, low_resolution purpose, and max_output_tokens default with 2048 lower-limit protection. This fully compensates for the schema's lack of descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it downloads from a direct link or cloud-reads from a YouTube page, then sends to Gemini for Chinese timeline-segmented description. This distinguishes it from sibling describe_video by focusing on URL inputs, with explicit mention of supported URL types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context on when to use: direct video file links or YouTube page links. It also lists exclusions (Bilibili/Douyin/TikTok unsupported) and error behavior. However, it does not explicitly contrast with sibling describe_video beyond referencing it for parameter semantics, so a slight gap in direct alternative guidance exists.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
estimate_costARead-only
估算把某个本地视频交给 Gemini 识别大概要花多少输入 token,让你发大视频前心里有数。
优先用 ffprobe 读真实时长;读不到(没装 ffprobe / 格式怪)则按文件大小粗估并注明。
Args: path: 本地视频文件路径。
Returns: 一段中文预估说明(文件大小、时长、标清/低清 token 估算、上传通道)。
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses the estimation method (prefer ffprobe, fallback to file-size estimate) and notes that approximations are marked. The readOnlyHint annotation is consistent, and the description adds meaningful behavioral context beyond the annotation without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a clear purpose statement, a method note, and structured Args/Returns sections. Every sentence adds value, and it is appropriately front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one parameter and no output schema, the description is complete. It explains the input, the estimation logic, and the return value format, ensuring an agent can invoke it correctly without additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description compensates by explaining that 'path' is a local video file path. While minimal, it clarifies the only parameter's role and local nature, which is sufficient for a single-param tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: estimating input token costs for sending a local video to Gemini. It uses a specific verb ('估算') and resource ('本地视频'), and is distinct from sibling tools like describe_video or get_upload_url.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use the tool ('让你发大视频前心里有数'), indicating it's for pre-upload cost estimation. It does not explicitly mention alternatives or when not to use, but the context is sufficient to differentiate from siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_upload_urlARead-only
获取"把文件推到本服务器"的上传地址——用于把 claude.ai 聊天里上传/沙盒里生成的文件搬到服务器再识别。
典型流程(在 claude.ai 的代码沙盒里执行): 1. 调本工具拿到上传地址; 2. requests.post(上传地址, files={"file": open("/mnt/user-data/uploads/xxx.mp4", "rb")}); 3. 用响应 JSON 里的 saved_path 调 describe_video 或 view_media。
Returns: 上传地址与用法说明;本地 stdio 模式下没有上传端点,会返回相应提示。
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, and the description adds behavioral context such as the return value (upload address and usage instructions) and the mode-dependent behavior. It discloses that the tool itself does not upload but returns an address, and explains the edge case where no endpoint exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a one-sentence purpose, a numbered workflow, and a brief return summary. Every sentence adds value, with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple zero-parameter utility, the description is complete: it explains the purpose, the exact HTTP POST usage, the expected response field (saved_path), and the follow-up calls to other tools. It also covers the local stdio mode limitation. No output schema exists, but the description adequately conveys return behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema fully covers parameter semantics. The description doesn't need to explain parameters; it instead explains the workflow and return value, which is appropriate for a 0-param tool. Baseline 4 per instructions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool gets an upload URL to push files to the server for recognition. It uses a specific verb+resource and distinguishes itself from sibling tools like describe_video/view_media, which process files rather than provide upload access.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly outlines when to use the tool (to move files from claude.ai chat/sandbox to the server) and provides a step-by-step workflow. It also notes a key limitation (local stdio mode has no upload endpoint), giving clear usage context without ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
view_mediaA
把一张【图片】、或【视频的某一帧】作为图片内容直接返回,让调用方模型亲眼看到画面。
path 是图片(png/jpg/jpeg/webp/gif):直接返回该图(长边超出 max_dimension 会等比缩小)。 GIF 只返回首帧(想感知整段动画请用 describe_video)。
path 是视频:给了 timestamp(秒)就抽那一帧;没给则抽正中间那一帧。需要本机有 ffmpeg。
与 describe_video 的分工:describe_video 让 Gemini 看视频写【文字】;view_media 把【画面本身】投给 你(调用方模型)看。stdio / HTTP 模式都可用。
Args: path: 本地图片或视频文件路径。 timestamp: 仅对视频有效,抽取该秒(float)的一帧;不填则取中间帧。 max_dimension: 返回图片的长边上限像素,默认 1024(超出等比缩小,不放大;范围 16~4096)。
Returns: 一张图片内容(MCP ImageContent);出错时返回一句中文说明。
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| timestamp | No | ||
| max_dimension | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and excels: it discloses image downscaling to max_dimension, GIF first-frame-only behavior, video mid-frame fallback, the local ffmpeg prerequisite, and error return format ('Chinese explanation'). This goes well beyond a simple 'view media' statement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a one-sentence purpose, followed by well-separated sections for image vs. video behavior, tool differentiation, arguments, and return type. Every sentence earns its place; there is no fluff or repetition despite the detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite lacking annotations and output schema, the description covers all needed context: return type (MCP ImageContent), error behavior, external dependency (ffmpeg), supported formats, scaling behavior, and runtime modes (stdio/HTTP). It also prevents misuse by referencing describe_video for animation/text needs, making it complete for both selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema properties have no descriptions (0% coverage), but the Args section adds rich meaning: path is a local file path, timestamp is video-only and measured in seconds, max_dimension has a default (1024), range (16–4096), and behavior (shrink only, never enlarge). This fully compensates for the schema's silence.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'return an image or a video frame as image content' to the calling model. It clearly distinguishes itself from the sibling tool describe_video by stating the division of labor: describe_video produces text, view_media returns the actual visual content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage guidance is provided, naming describe_video as the alternative when a textual description is needed or when the whole GIF animation is required. It also clarifies when timestamp should be supplied for videos and the default behavior if omitted, making the decision boundary between tools unmistakable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
describe_video - First observed
describe_video_url - First observed
estimate_cost - First observed
get_upload_url - First observed
view_media
TDQS
Scored across 5 tools
Each tool serves a clearly distinct purpose: cost estimation, local video description, URL-based description, frame viewing, and upload retrieval. The two description tools are cleanly separated by input source (local path vs URL) with explicit parameter names, eliminating ambiguity.
All tools follow a consistent verb_noun snake_case pattern (e.g., estimate_cost, describe_video, view_media, get_upload_url). The describe_video_url variant appropriately uses a suffix to indicate its remote input mode, preserving overall consistency.
With five tools, the server is well-scoped for video understanding workflows. Each tool covers a distinct step in the process—cost planning, local/remote description, visual extraction, and file upload—without redundant or missing functionality.
The tool surface fully covers the expected video analysis lifecycle: estimating token usage, uploading or referencing videos, describing content from local/URL sources, and examining frames. No essential operation is missing, and unsupported platform limitations are explicitly documented as out of scope.
Maintenance
Related MCP Connectors
Analyze images and videos with Gemini to get fast, reliable visual insights. Handle content from U…
- RendobarOAuthcom.rendobar
Transform video, audio and images, and generate media from prompts. FFmpeg, captions, models.
Give AI random access to video: timestamped contact sheets + zoom into any start/end range.
Transcode, host and caption video from a prompt. Fifteen tools, nine read-only, nothing deletes.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables conversational analysis of YouTube videos using Gemini 2.5 Pro, supporting multi-turn sessions, direct URL processing, and local video uploads.101MIT
- FlicenseAqualityDmaintenanceExtracts timestamped screenshots from local videos, enabling Claude to produce visual walkthroughs without audio analysis or cloud processing.4-
- FlicenseAqualityDmaintenanceEnables local media processing (video/audio) using FFmpeg and FFprobe, allowing frame extraction, audio conversion, and metadata retrieval through natural language.5-
- FlicenseNot gradedqualityDmaintenanceBridges Claude and video content by extracting keyframes and transcribing audio, enabling Claude to analyze video files.-