Inspiration

What it does

How we built it

Challenges we ran into

Accomplishments that we're proud of

What we learned

What's next for Clipper Alexa+: a voice-driven video clipper over MCP

Inspiration

Clipper already turns a long video into short captioned clips. For the Alexa+ track we wanted a voice assistant to drive it, so we added a self-hosted MCP server. This is an existing open-source clipper, updated during the hackathon window with a self-hosted MCP server. It is not affiliated with Amazon. The page at /alexa is a simulated Alexa+ experience, which the track allows.

Live app: https://clipper-production-1dab.up.railway.app MCP endpoint: https://clipper-production-1dab.up.railway.app/mcp

What it does

You talk to it the way you would talk to Alexa+. "Clip the best moments from this podcast." It starts a clip job on a video or podcast you own, then tells you, in a sentence or two, when the job is done, which moments are worth posting, how long they are, why they work, whether they fit an audience, and where the share links are. The links stay on screen. The voice does not spell them.

On the public demo it will not download a link. It clips a built-in sample talk, or a file you upload on the Clipper page. On a private server it accepts a YouTube link or a direct media file.

How we built it

  • MCP server. Official Python MCP SDK 2.3, Streamable HTTP, protocol 2025-11-25 or later, mounted at /mcp inside the same process that already serves the Flask UI. One Railway service, no second deploy.
  • Tools. start_clip_job, get_job_status, list_top_clips, get_audience_fit, get_clip_links. Each returns a short spoken line plus structured content. A guide resource, a per-job resource, and two prompts (clip_a_video, recap_job) sit next to the tools.
  • Same pipeline. Jobs go through the existing queue: acquire, transcribe, pick clips (GLM, Nebius Nemotron, or the offline heuristic), optional Qloo audience fit, ffmpeg, sidecar JSON.
  • Simulated Alexa+. /alexa takes typed or spoken requests (Web Speech API). GLM, through the existing provider layer, chooses one tool and writes the reply. Keys stay in the environment. With no GLM key, a small parser calls the same tools so a judge can still walk the flow offline.
  • Guardrails. Bearer auth is optional (MCP_AUTH_TOKEN). The public demo is open unless MCP_REQUIRE_AUTH=1. Per-minute and per-hour caps, plus the existing demo queue cap, keep a public session from running up model cost. The public demo still refuses remote downloads and browser cookies. Direct downloads on a private server reject private hosts and oversized files.

Challenges

  • The clipper was a Flask app. Streamable HTTP is ASGI. The process now runs under uvicorn: MCP on /mcp, Flask everywhere else, one lifespan that starts the MCP session manager.
  • Voice and JSON want different shapes. Tool results keep a spoken sentence in the text content and the job id, scores, and links in structured content, so a client can talk without reading a URL aloud.
  • The public demo must not become an open YouTube downloader. The voice tool still had to be useful, so the sample talk (a synthetic video this repo generates) is a first-class source, and link downloads stay off while PUBLIC_DEMO=1.
  • DNS-rebinding protection in the MCP SDK rejects unknown Host headers. Localhost works immediately. A public hostname has to be allowlisted; Railway's public domain is picked up automatically.
  • Audience fit only exists when a Qloo key is configured. The tool says so in one sentence instead of failing inside the renderer.

Accomplishments

  • One Railway service, no second deploy: the MCP server is mounted at /mcp inside the same process that already serves the UI.
  • Five working MCP tools plus a guide resource, a per-job resource, and two prompts, each returning a short spoken line alongside structured content.
  • A simulated Alexa+ page at /alexa that takes typed or spoken requests and drives the real MCP tools.
  • Public-demo guardrails: optional bearer auth, per-minute and per-hour rate caps, and no remote downloads in the public demo.

What we learned

  • Voice and JSON want different shapes: keep a spoken sentence in the text content and the job id, scores, and links in structured content, so a client can talk without reading a URL aloud.
  • Streamable HTTP is ASGI, so a Flask app has to move under uvicorn with one lifespan that starts the MCP session manager.
  • DNS-rebinding protection in the MCP SDK rejects unknown Host headers; a public hostname has to be allowlisted (Railway's public domain is picked up automatically).
  • Optional features like Qloo audience fit should say so in one sentence instead of failing inside the renderer.

What's next

  • A real Alexa+ skill registration once the self-hosted MCP endpoint is public, using the same five tools.
  • Optional bearer auth turned on for the hosted demo if traffic grows, with the simulated page staying same-origin.
  • Richer podcast input (an episode the caller already uploaded) without ever fetching links in the public demo.
  • Short spoken progress while a job is still transcribing, pushed over the MCP session instead of polled.

Built With

Share this project:

Updates

Submission history