Distributed Video QA MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| DVQA_VERIFY | No | Verify every video_ask call by default. | off |
| JINA_API_KEY | No | Key for the hosted embedding API (DVQA_EMBED_API_KEY overrides). | |
| DVQA_EMBED_DIM | No | Embedding dimension (Jina v4 supports 128–2048). | 1024 |
| DVQA_EMBED_TPM | No | Token-per-minute budget; set it to your Jina tier. | 90000 |
| DVQA_STATE_DIR | No | Directory for the index, media and downloads. | ~/.local/state/distributed-video-qa-mcp |
| DVQA_HTTP_TOKEN | No | Bearer token for HTTP mode. | |
| DVQA_MAX_FRAMES | No | Per-video frame budget. | 600 |
| DVQA_CPU_WORKERS | No | Decoder parallelism; defaults to half the CPU cores. | |
| TYPESAFE_API_KEY | No | Enables Jev verification. | |
| DVQA_COOKIES_FILE | No | Netscape cookies file for sign-in-only videos. | |
| DVQA_MAX_DURATION | No | Maximum allowed duration; larger sources are refused. | 6 h |
| DVQA_MAX_FILESIZE | No | Maximum allowed file size; larger sources are refused. | 8 GiB |
| DVQA_VERIFY_MODEL | No | Pinned judge model used for verification. | jev-1.14.0 |
| DVQA_ALLOWED_ROOTS | No | Directories where local files may be read and written; defaults to home and tmp in stdio mode and none in HTTP mode. | |
| DVQA_EMBED_API_KEY | No | Overrides JINA_API_KEY for the hosted embedding API. | |
| DVQA_EMBED_BACKEND | No | Embedding backend: mlx (local, Apple Silicon), jina (hosted API), or auto. | auto |
| DVQA_INGEST_HEIGHT | No | Download height for indexing. | 720 |
| DVQA_EMBED_IMAGE_PX | No | Long side of frames sent for embedding; cost grows with area. | 448 |
| DVQA_FRAME_INTERVAL | No | Frame sampling cadence in seconds. | 5 |
| DVQA_TRANSCRIBE_API_KEY | No | API key for the OpenAI-compatible transcription endpoint. | |
| DVQA_TRANSCRIBE_BACKEND | No | Transcription backend: mlx, faster-whisper, api, or none (frames only). | auto |
| DVQA_ALLOW_PRIVATE_HOSTS | No | Permit URLs on private or loopback addresses. | |
| DVQA_MAX_CONCURRENT_JOBS | No | Job parallelism. | 2 |
| DVQA_TRANSCRIBE_BASE_URL | No | Base URL for any OpenAI-compatible transcription endpoint. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Download, index and question video. Every tool returns typed structured content. Error text reads 'Error executing tool : : — '; branch on .
Flow:
video_ingest(source) with a URL or local path (video_ingest_batch for several, or a playlist). It returns a Job; call video_job(job_id, wait_seconds=60) until status is "succeeded". The result carries the video_id.
video_ask(question) returns the most relevant moments: timestamped transcript plus the frames as images. Answer from that evidence and cite timestamps as m:ss. If evidence.best_* similarities are low and keyword_matches is 0, say the video does not cover it.
Narrower tools: video_search (ranked hits), video_find_phrase (every exact occurrence), video_transcript (exact wording), video_frames (look at any instant, full resolution), video_chapters (structure), video_clip (export a segment).
To only save a file: video_probe(url) shows each quality and whether it needs an audio merge; video_download(url) merges the best audio in by default.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| video_statusA | Readiness and capacity: FFmpeg, yt-dlp and its JavaScript runtimes, the transcription and embedding
backends, limits, and index size. |
| video_probeA | Show what a link offers before downloading: title, length, and each quality with its size and whether it has sound on its own or needs the audio track merged in (most qualities above 360p do). |
| video_downloadA | Save a link to a file. Fetches video and audio streams in parallel fragments and muxes them into one playable file, preferring H.264/AAC for MP4 so it opens everywhere. Returns a Job whose result is a DownloadReport. |
| video_ingestA | Download (for a URL), transcribe, sample frames and embed, so the video can be searched and questioned. Speech and frame work run in parallel. Re-ingesting reuses finished stages, so a failed or interrupted job resumes. Returns a Job; its result holds the video_id, counts and timings. |
| video_ingest_batchA | Start one ingest job per source. Playlist and channel URLs expand to their first |
| video_jobA | A job's status, stage and progress, optionally waiting for it to finish. Progress is also streamed as MCP progress notifications while waiting. |
| video_jobsB | Recent download and ingest jobs, newest first. |
| video_cancelA | Stop a queued or running job. Stages that already finished stay in the index and are reused. |
| video_askA | The moments most relevant to a question, as evidence: for each, the transcript around it with
timestamps and the frames from it as images (in |
| video_searchA | Ranked hits from three channels fused by weighted reciprocal rank: meaning-based transcript search, keyword (BM25) search, and text-to-image search over frames. 'The slide with the pricing table' finds the frame even if nobody said it. Each hit lists the channels that matched it, with rank and raw score. |
| video_search_by_imageB | Where a picture, logo, chart or slide appears: frames that look like it, and passages about it. |
| video_find_phraseA | Every transcript segment containing the exact phrase, in time order. Use it to count mentions or collect every place a name or number comes up; use video_search for meaning rather than wording. A phrase split across two segments is not matched. |
| video_transcriptA | What was said, for the whole video or a range: timestamped lines, plain text, SRT, WebVTT, or JSON segments. Page through long videos with start and end. |
| video_framesA | Frames as images, at given timestamps or spread across a range. With exact=true each is decoded from the source at that instant and at higher resolution than the indexed samples, for reading small text. |
| video_chaptersA | Chapters with spans, opening words and distinguishing keywords. Uses the uploader's chapters when the source has them; otherwise finds topic shifts in the transcript embeddings (frames for silent video). |
| video_clipB | Cut a time range into its own MP4 with audio. Stream copy is instant; exact re-encodes. |
| video_listA | Every video in the index with its id, title, length, status and index counts. |
| video_infoC | Source, dimensions, language, index counts, completed stages and the uploader's description. |
| video_deleteA | Delete a video's transcript, frames and vectors. A file you ingested by path is never deleted; only the server's own downloaded copy and extracted frames are. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| video_brief | Ingest a video if needed and produce a structured brief: thesis, chapters, key claims, open questions. |
| video_fact_check | List the checkable claims a video makes, each with its exact wording, timestamp and on-screen support. |
| video_study_notes | Turn a lecture or tutorial into structured notes with definitions, steps and the slides that matter. |
| video_compare | Answer one question across several videos and show where they agree and disagree. |
| video_find_moment | Locate a moment by what was said or shown and verify it visually. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| library | Every indexed video with id, title, length and status. |
TDQS
Scored across 19 tools
Most tools target a distinct resource+action, and descriptions actively police the boundaries (video_find_phrase for exact wording vs video_search for meaning; video_ask for evidence vs video_search for ranked hits). The weaker spots are video_status / video_info / video_probe, which all read as 'tell me about something' and require reading descriptions to separate system readiness, indexed-video metadata and pre-download link inspection.
Every tool carries the same `video_` prefix, so the namespace is instantly recognizable and scannable. However, the suffix alternates between verbs/actions (download, ingest, ask, search, delete, cancel) and nouns (status, info, transcript, frames, chapters), and video_job vs video_jobs differs only by plurality, which is a minor readability wart rather than a real inconsistency.
19 tools is on the heavier side of the ideal band, but the domain genuinely spans an ingest pipeline, job management, retrieval (three search channels), transcript/frame/chapter inspection, and clipping, so nearly every tool earns its slot. The one arguable redundancy is video_download sitting alongside video_ingest, though they serve different ends (get a file vs build a searchable index).
The lifecycle is well covered: probe → download/ingest/batch → job status/list/cancel → list/info → search/ask/transcript/frames/chapters/clip → delete. Remaining gaps are minor: there is no corpus-level or cross-video question answering despite batch ingest, no re-index/refresh of a single video, and no way to prune job history, but agents can work around all of these.