Skip to main content
Glama

frame-grab-mcp

CI License: MIT MCP

Give your AI assistant eyes on your videos.

frame-grab-mcp is a Model Context Protocol server that returns video frames as images — so Claude and other vision models can actually look at your footage. Grab a frame, sample a clip, see the whole video as one contact sheet, detect every cut, auto-pick the sharpest thumbnail and export it at the right size for YouTube, Reels, TikTok or LinkedIn, or make a GIF.

Runs locally with ffmpeg. Your footage never leaves your machine.

You:    Look at ~/Exports/reel_v4.mp4 and tell me where the pacing drags.
Claude: [contact sheet + scene detection] 31 cuts in 42s (avg 1.4s), but shots 18–20
        run 4.1s, 3.8s and 5.2s — that's the product demo section around 0:24–0:37.
        Everything else cuts every 1–1.5s, so that stretch will feel slow.
You:    Make a YouTube thumbnail from the sharpest frame.
Claude: Saved reel_v4_youtube_thumb.jpg (1280x720, 214 KB) from 00:00:08.4.
        Here are 4 runner-ups if you'd prefer a different shot.

Tools

Tool

Returns

What it does

grab_frame

🖼 image

Frame at a timestamp (12.5, 1:23, 00:01:23.400, 50%). Optionally saves full-res JPG/PNG/WebP.

sample_frames

🖼 images

1–24 frames evenly spaced (or at exact times) across the clip or a range.

contact_sheet

🖼 image

One grid of evenly spaced frames with timestamp labels and a title bar. The cheapest way to "watch" a video.

detect_scenes

table + 🖼

Every cut with start/end/length, shots per minute, shortest/longest shot, a sheet of each scene's first frame, optional CSV.

make_thumbnail

🖼 image(s)

Platform-sized thumbnail. Auto-pick rejects black/white/flat frames and ranks by sharpness, contrast, exposure and color, then shows runner-ups. Or pass at.

extract_frames

file list

Save stills to a folder: every N seconds, N evenly spaced, one per scene, or exact timestamps.

make_preview

file + 🖼

Optimized looping GIF (custom palette), silent MP4 loop, or animated WebP from a section.

check_setup

text

Confirms ffmpeg/ffprobe, required filters, and the label font.

Thumbnail presets

id

Size

Notes

youtube

1280x720

Auto-compressed to stay under YouTube's 2 MB limit

youtube_shorts

1080x1920

instagram_reels_cover

1080x1920

The profile grid shows the middle 3:4 — keep the subject there

instagram_grid

1080x1440

3:4 profile grid tile

instagram_feed

1080x1350

4:5

tiktok_cover

1080x1920

square

1080x1080

x

1600x900

linkedin

1200x627

Or pass custom width / height. Cropping uses anchor_x / anchor_y (0 = left/top, 1 = right/bottom) so you can keep a subject who isn't centered.


Related MCP server: video-tools-mcp

Requirements

  • Node.js 20+

  • ffmpeg + ffprobe

    • macOS: brew install ffmpeg · Ubuntu: sudo apt install ffmpeg · Windows: winget install ffmpeg

  • A vision-capable MCP client (Claude Desktop, Claude Code, Cursor…) to see the returned images.

Binaries are found via FFMPEG_PATH / FFPROBE_PATH, then PATH, then common folders like /opt/homebrew/bin (Claude Desktop on macOS uses a minimal PATH). Timestamp labels use a system font (Arial/Helvetica on macOS, DejaVu on Linux, Arial on Windows); set FRAME_GRAB_FONT=/path/to/font.ttf to choose your own. If your ffmpeg can't draw text, sheets are made without labels.

Install

Claude Desktop

Settings → Developer → Edit Config:

{
  "mcpServers": {
    "frame-grab": {
      "command": "npx",
      "args": ["-y", "github:anshumanofficial2002-cpu/frame-grab-mcp"]
    }
  }
}

Claude Code

claude mcp add frame-grab -- npx -y github:anshumanofficial2002-cpu/frame-grab-mcp

Cursor / Windsurf / VS Code / other clients

{
  "frame-grab": {
    "command": "npx",
    "args": ["-y", "github:anshumanofficial2002-cpu/frame-grab-mcp"]
  }
}

From source

git clone https://github.com/anshumanofficial2002-cpu/frame-grab-mcp.git
cd frame-grab-mcp && npm install && npm run build
# point your client at: node /absolute/path/to/frame-grab-mcp/dist/index.js

Example prompts

  • "What's on screen at 0:42 in interview_cam_b.mov? Is the lower third readable?"

  • "Make a 5×4 contact sheet of client_raw.mp4 and tell me which shots are usable b-roll."

  • "Count the cuts in this reference reel and give me a shot list with timings."

  • "Pick the best frame from vlog_ep3.mp4 for a YouTube thumbnail — the subject is on the right, keep them in frame."

  • "Make a Reels cover from 00:12.3."

  • "Export one still per scene from montage.mp4 into ~/Desktop/stills as PNG."

  • "Make a 3-second GIF of the logo reveal at 0:05 for X, under 5 MB."

  • "Sample 12 frames from the first minute and check whether my white balance shifts between shots."


Tool reference

Timestamps everywhere accept seconds (12.5), MM:SS, HH:MM:SS.mmm, or a percentage of the duration ("75%"). Range params start / end limit any analysis to part of the clip.

grab_frame

at ("50%"), max_width (1024), format (jpeg|png), save_path, overwrite.

sample_frames

count (8, max 24) or times (list), start, end, max_width (512).

contact_sheet

cols (4), rows (4), start, end, tile_width (320), labels (true), title (true), background (0x111111), font_file, save_path, overwrite.

detect_scenes

threshold (0.3; lower = more sensitive), min_scene_seconds (0.4; ignores flash frames), start, end, include_sheet (true, up to 30 scenes), max_rows (200), csv_output_path, overwrite.

make_thumbnail

Param

Default

Notes

preset

youtube

See table above

width / height

—

Custom size

at

auto

Use this frame instead of auto-picking

start / end

whole clip

Where to look (auto mode skips the first/last 3% for titles and fades)

candidates

24

Frames evaluated

show_candidates

4

Runner-ups returned as images

anchor_x / anchor_y

0.5

Crop anchor

output_path

<name>_<preset>_thumb.jpg

.jpg, .png, .webp

quality

92

overwrite

false

extract_frames

output_folder, mode (count | interval | scenes | timestamps), count (12), interval_seconds, times, scene_threshold (0.3), start, end, format (jpg|png|webp), width, prefix, max_frames (200), overwrite. Files are named <prefix>_<HH-MM-SS-mmm>.<ext>.

make_preview

start (0), duration (4, max 60), output_path (<name>_preview.gif; .gif/.mp4/.webp), fps (12), width (480), colors (128), loop (true), dry_run, overwrite.


How it works

  • Frames are decoded with accurate input seeking (-ss before -i), auto-rotated, scaled with Lanczos, and piped straight back as JPEG/PNG — nothing touches disk unless you ask.

  • Scene detection: ffmpeg's select='gt(scene,T)' on a 320 px proxy for speed.

  • Thumbnail scoring: signalstats (brightness, contrast, saturation) and blurdetect (sharpness) on each candidate. Black, white, flat and detail-less frames are rejected.

  • Contact sheets: one ffmpeg graph with a fast seek per tile, tile for the grid and drawtext for labels. The title is drawn from a temp text file, so odd file names are safe.

  • GIFs: two-stage palette (palettegen + paletteuse) for small, clean files.

HDR footage is not tone-mapped, so frames from HDR clips (e.g. iPhone HDR video) can look washed out.

Safety

  • ffmpeg runs via spawn with argument arrays — no shell.

  • Existing files are never overwritten unless overwrite: true, and outputs can't replace the source video.

  • No network access, no telemetry.

Development

npm install
npm run build
npm test          # unit tests + end-to-end tests on a generated clip with known cuts
npm run inspect   # MCP Inspector

dist/ is committed so npx github:… works without a build; CI verifies it matches src/.

License

MIT © 2026 Anshuman

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers