MCP server that turns any video (local file or URL) into frames + transcript for Claude.
Four tools with clear verb-noun naming (analyze_, get_, extract_, list_). Descriptions are present and substantive (100-250 chars), explaining WHAT and WHEN. However, parameter descriptions lack depth, many omit format constraints, valid ranges, and dependency hints. Input schemas are properly typed but sparse on validation rules. No output schemas documented. Error handling is minimal; no recovery guidance or actionable error messages visible in code. Missing tool annotations (readOnlyHint, idempotentHint). All tools are READ_ONLY by risk classification, but this is not formally declared in the schema.
Analyze a video into frames + transcript + metadata. Provide exactly ONE source: - file_path: local path to a video file (already on disk). - url: direct/streaming URL (yt-dlp for known sites, HTTP otherwise). frame_interval: seconds between sampled frames (default 1.0 = one per second). Denser sampling: 0.5 / 0.25 / 0.1; sparser: 2 / 5; or any custom value. The total is capped by the frame budget so long/dense videos can't flood context. Ignored by the native Gemini backend (it ingests the whole video). The backend (local whisper.cpp / OpenAI / Groq / native Gemini) is chosen automatically from configured keys and named in the result metadata. Results are cached per (file-hash, backend, frame_interval); pass force_refresh=true to recompute.
Extract frames at specific timestamps. timestamps accepts seconds ("12", "12.5") or "MM:SS" / "HH:MM:SS". Tier 1/2 return real frame images; with the Gemini backend you get a textual description of those moments instead (no local frame cutting).
Fast path: return only the transcript text (no frame images). Same inputs and backend selection as analyze_video. With the Gemini backend, returns Gemini's analysis text instead of a plain transcript.
List previously analyzed videos from the cache, with the backend used for each.
Parameter descriptions lack format constraints and valid ranges. E.g., 'frame_interval' says 'seconds between sampled frames (default 1.0)' but omits min/max bounds, whether fractional values are allowed, or what happens if interval exceeds video duration. 'timestamps' in extract_frames_at accepts 'seconds or MM:SS / HH:MM:SS' but does not specify regex pattern or validation rules.
No output schemas documented. Callers cannot know what fields to expect from analyze_video (frames structure? transcript format? metadata fields?), get_video_transcript_only (plain text or structured?), or list_recent_analyses (array of what objects?). LLMs must guess downstream field names, risking broken tool chains.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 56 | 2026-07-28+ | v2 |
No error handling guidance in tool descriptions. Code shows FfmpegError and subprocess failures are possible (ffprobe/ffmpeg return codes checked), but tool descriptions do not explain what errors can occur, whether they are retryable, or what the LLM should do next. E.g., 'URL not found' or 'ffmpeg not installed' are silent failures.
Mutually exclusive parameters (file_path vs url) are documented in the description text but not enforced in the schema. JSON Schema should use oneOf or explicit validation. LLMs may pass both, causing ambiguous behavior.
Tool annotations missing. All four tools are READ_ONLY (no state modification), but the schema does not declare readOnlyHint=true. This prevents clients from optimizing caching, retry logic, or safety checks. Idempotent tools (analyze_video with force_refresh=false uses cache) should declare idempotentHint.