Skip to main content
Glama

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 .gif natively (sent as raw image/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_resolution is a cost-saving switch; persona lets Gemini narrate in character; hint lets 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); prompt fully 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, just path becomes url;

    • 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 to describe_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 exceeds max_dimension (default 1024, adjustable 16–4096). GIFs return only their first frame (use describe_video if 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 (uses ffprobe for 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-flash

You 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

GEMINI_API_KEY

Yes

Your Gemini API key

GEMINI_MODEL

No

gemini-3.5-flash

Model identifier

GEMINI_BASE_URL

No

https://generativelanguage.googleapis.com/v1beta

API base URL; only change this if you're proxying

GEMINI_THINKING_LEVEL

No

high

One of minimal/low/medium/high; set minimal to save cost

GEMINI_AGENTIC_MODEL

No

empty (falls back to GEMINI_MODEL)

Model used for agentic mode; only needed when the main model doesn't support it

GEMINI_MCP_HTTP_SECRET

Only for --http mode

The sole access lock for HTTP mode; server refuses to start without a real value

GEMINI_MCP_PUBLIC_BASE_URL

No

none (falls back to http://localhost:8768)

Public URL after tunneling; used by get_upload_url to build the upload link

(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.py

If 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.py

Verify it registered:

claude mcp list

Registering 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.

  1. Generate a random secret (run this from a terminal in the project directory):

    uv run python -c "import secrets; print(secrets.token_urlsafe(32))"
  2. Paste the output into this line in your .env (copy .env.example first if you don't have one yet):

    GEMINI_MCP_HTTP_SECRET=paste-the-generated-string-here

    Never 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.

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:

  1. Open the Cloudflare Zero Trust dashboard → Networks → Tunnels → select your tunnel → Configure.

  2. On the Public Hostname tab, click Add a public hostname:

    • Subdomain: pick something like gemini-video; Domain: your own domain (the final address will be gemini-video.yourdomain.com).

    • Service → Type: HTTP, URL: http://localhost:8768 (note: http, localhost, port 8768).

  3. 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:8768

It prints a https://random-name.trycloudflare.com address 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 a https://<machine-name>.<tailnet>.ts.net public address — append /mcp/<secret> the same way.)

Step 4: add it as a Custom Connector in claude.ai

  1. Open claude.ai → avatar → SettingsConnectors.

  2. Click Add custom connector.

  3. Name: anything you like, e.g. Gemini Video.

  4. 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.)

  5. 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_url tool plus server-level instructions, so Claude in claude.ai will automatically call get_upload_url when it sees a chat-uploaded file, POST it from the sandbox, and use the returned saved_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 that get_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.mp4 for me" → triggers describe_video.

  • "Narrate D:/videos/dance.mp4 like a snarky high schooler" → Claude passes a persona.

  • "This video is people playing five-in-a-row with eggs, describe D:/videos/eggs.mp4" → Claude puts your description into hint so the model can make sense of something abstract or meme-y.

  • "Describe this direct video link: https://example.com/clip.mp4" → triggers describe_video_url (downloads, then describes).

  • "Show me what D:/videos/monkey.mp4 looks like at the 8-second mark" → triggers view_media (pulls the frame at 8s for Claude to actually look at).

  • "Take a look at this picture, D:/pics/meme.png" → triggers view_media (feeds the image straight to Claude).

  • "About how many tokens would it cost to describe D:/videos/long.mp4?" → triggers estimate_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:

mode

What it does

When to use

auto (default)

agentic when the video is ≥ 5 minutes, static otherwise (static whenever the duration can't be read)

The set-and-forget choice

static

generateContent, fixed-rate frame sampling over the whole video (1 FPS by default)

Short clips, or when you want every second described

agentic

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) or m:ss (1:06); with only start, it looks 30 seconds ahead; fps defaults to 1 and is capped at 10;

  • If hint reads 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 (low_resolution=True)

~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

  • .mkv isn't on Gemini's officially supported list; this server sends it as video/x-matroska on a best-effort basis. If it gets rejected, convert to mp4 first.

  • 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_MODEL for a Gemini 2.5-series model: 2.5 uses thinkingBudget instead of thinkingLevel, and the thinkingLevel this server sends by default may get rejected with a 400. The default 3.5-flash doesn't have this issue.

  • estimate_cost falls back to a rough size-based duration estimate when ffprobe isn't available, which can be noticeably off (the result says so).

  • view_media depends 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 — use describe_video to have the full animation understood.

  • describe_video_url only 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 --http mode; 500MB per file, 2GB total for temp_media/ (oldest files pruned first once that's exceeded).

  • Transport: stdio (local) by default; --http is 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 tools
describe_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 生成的视频内容描述文本(末尾可能带用量统计或截断提示)。

ParametersJSON Schema
NameRequiredDescriptionDefault
hintNo
pathYes
promptNo
personaNo
low_resolutionNo
max_output_tokensNo

TDQS

A4.8/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 生成的视频描述文本(末尾可能带用量统计或截断提示)。

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
hintNo
promptNo
personaNo
low_resolutionNo
max_output_tokensNo

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_costA
Read-only

估算把某个本地视频交给 Gemini 识别大概要花多少输入 token,让你发大视频前心里有数。

优先用 ffprobe 读真实时长;读不到(没装 ffprobe / 格式怪)则按文件大小粗估并注明。

Args: path: 本地视频文件路径。

Returns: 一段中文预估说明(文件大小、时长、标清/低清 token 估算、上传通道)。

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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_urlA
Read-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 模式下没有上传端点,会返回相应提示。

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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);出错时返回一句中文说明。

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
timestampNo
max_dimensionNo

TDQS

A5/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

  1. 5 tool updatesv0.1.0
    • First observeddescribe_video
    • First observeddescribe_video_url
    • First observedestimate_cost
    • First observedget_upload_url
    • First observedview_media

TDQS

A4.9/5.0

Scored across 5 tools

Disambiguation5/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness5/5

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

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers