Framesleuth

Framesleuth

MCP server that analyzes videos locally with frame-by-frame understanding and optional browser sidecars, producing structured context bundles for coding agents to fix bugs, add features, or build new functionality.

Category
访问服务器

README

<p align="center"> <img src="docs/logo/framesleuth-logo-256.png" alt="Framesleuth" width="128" height="128" /> </p>

Framesleuth

Local video → structured context for coding agents, exposed over MCP.

Give Framesleuth any video — a bug recording, a feature demo, a design walkthrough, a Loom, a phone capture — and it understands it frame-by-frame (plus optional browser sidecars) and produces a structured Context Bundle. It is MCP-ready, so any MCP client — a VS Code agent, another coding agent, or a custom system — can drive the analysis and consume the result to fix a bug, add or change a feature, or build a whole new feature/app grounded in what the video actually shows.

Capture happens outside this repo: any video works, or a browser capture extension can record a session and post the video + sidecars to this agent's local API. This repo is the analysis agent only.

Everything runs locally. Nothing leaves your machine.

Quick start

Want to go from a video to a grounded change inside VS Code? Follow Use with VS Code & Claude (MCP) — connect the bundled MCP server and turn a recording into a fix, a feature, or a new build.

Fastest: one command with Docker

Everything — the model server, the models, and the API — comes up with a single command. No Python, no virtualenv, no manual model setup.

git clone https://github.com/thestackhub1/framesleuth-agent.git
cd framesleuth-agent
docker compose up            # or: ./scripts/dev_up.sh

Compose loads docker-compose.override.yml automatically; that override adds the Ollama server, model-pull job, and Ollama model volume. The first run automatically pulls the vision + coder models (qwen2.5vl and qwen2.5-coder:7b, ~11 GB total) into a Docker volume, then starts the backend on http://127.0.0.1:8010. Subsequent runs are instant. It's ready when the health check reports healthy:

curl -s http://127.0.0.1:8010/v1/healthz | python -m json.tool   # "status": "healthy"

That's the whole setup — run your first analysis (below), or connect the MCP server in your editor (VS Code & Claude).

docker compose logs -f                  # follow progress / model download
docker compose down --remove-orphans    # stop  (add -v to also delete model volumes)

The stack runs its own Ollama on the internal Docker network only (its port is not published), so it never clashes with a native Ollama you may already run on :11434 — the only host port is the API on :8010.

Already run Ollama natively (with the models)? The Docker stack's Ollama is separate and would re-download them. Skip Docker and use the direct path below instead — it reuses your existing Ollama and is faster (especially on macOS, where Docker can't use the GPU).

macOS / no GPU: Docker runs the models on CPU, so the vision model is slow. NVIDIA GPU on Linux: uncomment the deploy: block on the ollama service in docker-compose.override.yml for acceleration.

To run only the backend container against a native/external model server, use docker compose -f docker-compose.yml up. The base compose file defaults to native Ollama on http://host.docker.internal:11434; override VLM_URL and CODER_URL for another server.

Run your first analysis (curl)

Once the API reports healthy (either setup path), go from a video to a Context Bundle in three calls — analysis is async (submit → poll → read):

# 1. Submit any screen recording (mp4/webm). Returns 202 { job_id, ... }
JOB=$(curl -s -F "video=@bug.mp4" http://127.0.0.1:8010/v1/analyze \
  | python -c "import sys, json; print(json.load(sys.stdin)['job_id'])")

# 2. Poll until state is "done" (queued → running → done)
curl -s "http://127.0.0.1:8010/v1/jobs/$JOB" | python -m json.tool

# 3. Read the Context Bundle
curl -s "http://127.0.0.1:8010/v1/report/$JOB" | python -m json.tool

Optional form fields on step 1: -F intent="why does save hang?", -F skill=bug_report, -F action=fix (GET /v1/skills and /v1/actions list the choices). Prefer a UI? Import the Postman collection — it chains these calls for you.

Run it directly (no Docker — fastest on macOS, best for development)

Prerequisites: Python 3.11+, uv, 8 GB+ RAM, and a local model server. ffmpeg is not required (PyAV bundles its own; ffprobe, if present, is used opportunistically to detect an audio stream).

git clone https://github.com/thestackhub1/framesleuth-agent.git
cd framesleuth-agent

# 1. Models — native Ollama (uses the Mac GPU) is the quick path
ollama serve &                                  # skip if already running
ollama pull qwen2.5vl && ollama pull qwen2.5-coder:7b

# 2. Install
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
python scripts/download_models.py               # optional: pre-warm ASR + check servers

# 3. Configure + start the API (binds 127.0.0.1:8010)
cp .env.example .env                            # already defaults to the Ollama path above
framesleuth-api                                 # or: uvicorn framesleuth.service.api:app --port 8010

# 4. Verify
curl -s http://127.0.0.1:11434/v1/models | grep -q qwen2.5vl && echo "VLM ready"
curl -s http://127.0.0.1:8010/v1/healthz | python -m json.tool   # status: healthy, vlm: ready

When /v1/healthz shows vlm: ready, recordings analyze with a real classification (analysis_quality.level = full/partial). With no vision model reachable, Framesleuth degrades gracefully — it still produces a valid Context Bundle from the browser sidecars (console errors, failed requests, clicks) and records what was thin in analysis_quality. Record with narration so the audio transcript (asr) stage contributes too.

Something not working? Run the setup doctor — it works with a plain python3 even when your virtualenv is broken, and prints a one-line fix for each problem (stale/missing venv, framesleuth-api not on PATH, ffmpeg/render prerequisites, backend or model server not reachable, wrong VLM_URL):

python3 scripts/doctor.py

Common gotcha: command not found: framesleuth-api or a uv pip install error about a missing interpreter means your active venv was deleted/moved. Fix it from the framesleuth directory: deactivate; unset VIRTUAL_ENV; uv venv && source .venv/bin/activate && uv pip install -e ".[dev]".

Stop

# Stop the backend: Ctrl+C in its terminal, or
pkill -f framesleuth-api

# Stop Ollama (optional — leaving it running keeps the model warm)
pkill -f "ollama serve"              # macOS app users: quit Ollama from the menu bar

Architecture

Any video (mp4/webm) + optional sidecars
    ↓
Local Analysis Service (pipeline)
    ├─ Preprocess (PyAV: duration/fps/dims)
    ├─ Transcript (faster-whisper)
    ├─ Keyframes (visual-delta change scoring)
    ├─ Understanding (local vision model — Qwen2.5-VL by default)
    ├─ Fusion + Classification
    ├─ Extraction → Context Bundle
    ├─ Summarize (skill/system-prompt-driven)
    └─ Grounding (workspace search)
    ↓
Context Bundle
    ↓
MCP server + local HTTP API
    └─ consumed by any MCP client (VS Code agent, other agents, capture extension)

Features

  • Frame-by-frame understanding using a local vision model (Qwen2.5-VL by default; engine-agnostic)
  • Adaptive keyframe selection — coverage-binned, visual-salience-ranked (AKS-style), with a build-aware budget for feature/design videos and perceptual-hash dedup that drops near-identical frames so the VLM budget is spent on distinct content
  • Bug and build — a feature class plus a structured build context (screens, UI components, a screen-to-screen user flow, design notes, and where to implement) so an agent can implement, not just diagnose
  • Error detection and extraction from console, OCR, and UI state
  • Corpus-aware grounding — error symbols or feature/UI nouns → ranked file:line (definitions preferred, distinctive symbols weighted via IDF + whole-word match), respecting .gitignore and bounded for large repos
  • Trust signals — per-field confidence (with cross-modal corroboration — agreeing signals reinforce each other) and a task-aware actionability (ready/thin/insufficient) alongside the pipeline quality level
  • Redaction-first design — secrets (passwords, tokens, keys) and PII (emails, Luhn-valid card numbers, SSNs/phones, cloud keys) are scrubbed from OCR, captions, the transcript, and the raw sidecar streams before any of it reaches a model or is persisted (bundle and the sibling timeline.json / sidecars.json / transcript.json)
  • Observability — per-stage timings on every bundle (stage_timings) and live on GET /v1/jobs/{id}, so you can see where analysis time went
  • Job lifecycle & delivery — cooperative cancellation (DELETE /v1/jobs/{id}, checked between frames), a hard per-job timeout (JOB_TIMEOUT_S), crash recovery (orphaned jobs are failed on restart, not left as zombies), SSE progress with explicit terminal events (GET /v1/jobs/{id}/events), a completion webhook (WEBHOOK_URL), real queue depth in /healthz, and TTL retention cleanup (BUNDLE_TTL_DAYS) swept at startup and periodically (RETENTION_SWEEP_INTERVAL_S)
  • Interaction overlay — a click/cursor sidecar with coordinates draws a marker on the matching keyframe, so the model sees where the user acted
  • Cleaner transcripts — faster-whisper voice-activity filtering (ASR_VAD_FILTER) drops silence before decoding; detected/forced language is recorded
  • OCR backstop (optional ocr extra) — a sparse VLM OCR on an error frame gets a second, independent Tesseract reading; a no-op without the extra
  • No data leaves your machine — fully local, no telemetry or cloud APIs
  • Engine-agnostic — swap Ollama, llama.cpp, or vLLM via config only
  • Works on any video — not just bug recordings. A general video (a demo, a walkthrough, a talk, a phone/real-world clip) yields a faithful summary + a timeline of key moments (summary, key_moments[]) instead of being forced into a bug shape; the bug-only fields (severity, expected/actual, repro steps) stay null rather than carrying fabricated placeholders
  • Structured output — canonical Context Bundle with evidence citations
  • Configurable response — pick a summary skill and an action mode (fix/implement/design/summarize/explain/triage/test/report/reproduce, auto-picked from the classification), plus a machine-readable suggested_actions menu and on-demand artifact renderers (markdown / GitHub issue / test plan)
  • Eval harness — model-free classification / grounding / citation / faithfulness suites (python scripts/eval_harness.py --behavioral) run in CI (GitHub Actions, on a 3.11/3.12 matrix: ruff, black, mypy --strict, pytest with a coverage gate, the eval harness against per-metric thresholds in evals/, and an OpenAPI-freshness check — plus a separate security job running pip-audit and pre-commit) on every push and PR; the faithfulness suite proves every emitted key moment and step cites real, resolvable evidence (no fabrication)
  • Resilient — handles no-audio videos, weak local models, low-confidence cases
  • HTML → video (frame-by-frame) — turn a self-contained HTML animation (CSS/JS/canvas) into MP4, GIF, or WebM via the render_html_video MCP tool or POST /v1/render-html. Captures the animation frame-by-frame under a paused virtual clock and encodes a color-correct H.264 MP4 (yuv420p+bt709, near-lossless) — full color, no dropped frames, no quality loss (up to 4K, 5–60 fps). Included by default in the Docker image (headless Chromium + ffmpeg). For the direct (non-Docker) path, add the render extra (see below); returns 503 with an actionable message when unavailable.

Enable & troubleshoot HTML → video

Using Docker (docker compose up)? HTML→video already works — the image bakes in Playwright + Chromium + ffmpeg. (Build with --build-arg INSTALL_RENDER=false for a slimmer image without it.) The steps below are for the direct path.

Why is Playwright not in the core install? It's an optional [render] extra, not a core dependency, because it pulls a ~150 MB headless-Chromium browser the core video→bundle pipeline never needs — the standard way to ship a heavy, feature-specific dependency. (av, opencv, faster-whisper are core because the pipeline requires them.) Install the extra and you're done — the Chromium build downloads automatically on your first render, so there's no separate playwright install chromium step:

# In the same environment the server runs in:
uv pip install -e ".[render]"        # or ".[all]" = dev + render
# ffmpeg must be on PATH (brew install ffmpeg / apt-get install ffmpeg)

# Restart framesleuth-api, then verify (Chromium fetches itself on first render):
curl -s http://127.0.0.1:8010/v1/healthz | python -m json.tool
# → "render": {"playwright": true, "chromium": <true after first render>, "ffmpeg": true}

Set FRAMESLEUTH_AUTO_INSTALL_BROWSER=0 to disable the auto-download and run playwright install chromium yourself (e.g. in a locked-down environment).

Other optional extra — ocr. For the dedicated OCR backstop on error frames, uv pip install -e ".[ocr]" and put the tesseract binary on PATH (brew install tesseract / apt-get install tesseract-ocr). It's a no-op when absent — the VLM still does OCR; the backstop only adds a second reading. Use ".[all]" for dev + render + ocr.

If render.ready is false, the render.hint field tells you exactly what's missing. The most common cause of "Playwright is not installed" despite following the steps is that framesleuth-api is running from a different environment than the one you installed into (the render.python field shows which interpreter the server uses) — or the server simply wasn't restarted.

Project structure

framesleuth/
├── framesleuth/              # Main package
│   ├── config.py            # Typed config (pydantic-settings)
│   ├── schemas.py           # Data contracts (Context Bundle, enums)
│   ├── errors.py            # Exception taxonomy
│   ├── logging_config.py    # Structured JSON logging, job-id correlation
│   ├── prompts.py           # VLM / classify / summary / fix prompt templates
│   ├── skills.py            # Built-in summary skills (summary, bug_report, ...)
│   ├── actions.py           # Action modes (fix/explain/triage/...) + suggested-actions menu
│   ├── render.py            # Artifact renderers (markdown / GitHub issue / test plan)
│   ├── clients/             # VLM, coder HTTP clients (OpenAI-compatible)
│   ├── pipeline/            # preprocess, asr, scenes, understand, fusion, classify,
│   │                        #   bug_extract, build_context, confidence, dedup, overlay,
│   │                        #   ocr, redact, summarize, sidecars, grounding, gif,
│   │                        #   atomic, html_render
│   ├── eval/                # harness.py — model-free behavioral suites
│   ├── orchestrator/        # graph.py — linear async stage pipeline
│   ├── jobs/                # store.py — SQLite job state + bundle index
│   ├── service/             # FastAPI HTTP endpoints
│   └── mcp_server/          # framesleuth MCP server (VS Code + any MCP client)
├── tests/                   # pytest tests + fixtures
├── scripts/                 # doctor.py (setup check), download_models.py, dev_up.sh,
│                            #   eval_harness.py, export_openapi.py
├── evals/                   # thresholds.json + baseline.json (the CI quality gate)
├── openapi.json             # generated API schema — the contract clients build from
├── postman/                 # HTTP API collection + environment
├── docs/                    # capabilities, use-with-vscode-and-claude, web-integration
└── pyproject.toml           # Dependencies and tool config

Development

Run tests

pytest tests/ -q                                        # fast: no coverage gate
pytest tests/ -q --cov=framesleuth --cov-fail-under=75  # what CI enforces

Regenerate the API schema (after changing any route)

python scripts/export_openapi.py --out openapi.json

CI fails if this file is stale — the website generates its typed client from it.

Run the eval gates

python scripts/eval_harness.py --behavioral   # see evals/README.md

Code quality

ruff check framesleuth tests
black --check framesleuth tests
mypy --strict framesleuth

Set up pre-commit hooks

pre-commit install

A short, focused set:

License

Apache-2.0


Capture client

Bug capture lives outside this repo. Any screen recording works — drive the agent directly with your own video file. A browser capture extension can also record a session, collect browser sidecars (console errors, failed requests, clicks), and post the video + sidecars to this agent's local API. CORS is allowlisted (WEB_ORIGINS, default: the hosted demo site

  • local dev) plus any chrome-extension:// origins you list in CHROME_EXTENSION_IDS (empty by default — a capture extension must add its own ID), and the agent answers Chrome's Private Network Access preflight — so both a capture extension and the "Try it" widget on framesleuth.com work against a locally running backend with no extra setup. The agent stays bound to loopback; CORS only controls which browser origins may read its responses.

Set API_TOKEN for anything beyond a single-user laptop. When set, every /v1 endpoint except /v1/healthz requires Authorization: Bearer <token>. CORS does not stop another local process — or a DNS-rebinding page — from sending requests to loopback; a token does. The Docker stack reads it from .env, and publishes the API on 127.0.0.1 only.

Status: Backend + pipeline + MCP server completed. Questions? Open an issue or check runbook.md for common questions.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选