<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sajidur</title>
    <description>The latest articles on DEV Community by Sajidur (@sevrin).</description>
    <link>https://dev.to/sevrin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4136179%2F1c86b58b-536d-456a-a593-a6f040c4c4d3.gif</url>
      <title>DEV Community: Sajidur</title>
      <link>https://dev.to/sevrin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sevrin"/>
    <language>en</language>
    <item>
      <title>I built an MCP server that lets AI agents investigate videos</title>
      <dc:creator>Sajidur</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:10:23 +0000</pubDate>
      <link>https://dev.to/sevrin/i-built-an-mcp-server-that-lets-ai-agents-investigate-videos-32pm</link>
      <guid>https://dev.to/sevrin/i-built-an-mcp-server-that-lets-ai-agents-investigate-videos-32pm</guid>
      <description>&lt;p&gt;Hey DEV! First post here 👋&lt;/p&gt;

&lt;p&gt;I've been working on an open-source project called &lt;strong&gt;Urma&lt;/strong&gt;, a local MCP server that lets AI hosts retrieve captions and frames from videos. I recently shipped its first stable release, so I thought I'd introduce it here.&lt;/p&gt;

&lt;p&gt;The idea is quite simple. Let's say you're asking an AI agent to research how a particular feature works. It searches the documentation, goes through a few GitHub issues (including one closed in 2021 with no explanation), and eventually finds a recording where someone demonstrates the feature.&lt;/p&gt;

&lt;p&gt;That recording could be a 40-minute conference talk, with the relevant part buried somewhere around minute 37. Naturally.&lt;/p&gt;

&lt;p&gt;An agent with web access can find the recording itself. With Urma connected to its MCP host, it can then inspect the video, search for relevant captions, and retrieve frames around the moments it wants to examine.&lt;/p&gt;

&lt;p&gt;I wanted that to fit naturally into the way agents already research things. Cause sometimes the most useful information is sitting inside a video, while the documentation confidently says "Coming soon."&lt;/p&gt;

&lt;h2&gt;
  
  
  What Urma does
&lt;/h2&gt;

&lt;p&gt;Urma works through five MCP tools. An investigation begins with &lt;code&gt;inspect_video&lt;/code&gt;, which opens a source and returns an investigation reference. The host uses that reference when requesting captions or visual evidence.&lt;/p&gt;

&lt;p&gt;For example, suppose a tutorial includes the line:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Now I'm turning on dark mode."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A caption search can locate where the presenter said that. But to answer whether dark mode was actually enabled, the agent needs to look at the screen.&lt;/p&gt;

&lt;p&gt;The presenter might have turned it on. The UI might still be bright enough to illuminate the entire room. The caption alone won't settle that.&lt;/p&gt;

&lt;p&gt;Urma can retrieve frames around that timestamp. The host can inspect the images, request additional frames if needed, and decide what the evidence supports.&lt;/p&gt;

&lt;p&gt;This distinction influenced quite a bit of how I built the project. Urma records which source snapshot an investigation uses and which observations have been returned. A visual overview might contain 12 sampled frames, but of course those samples don't tell us everything that happened between them.&lt;/p&gt;

&lt;p&gt;Calling 12 frames complete video coverage would be a bit like saying your tests passed because TypeScript compiled successfully.&lt;/p&gt;

&lt;p&gt;I also spent time getting timestamp handling right. Video containers and streams can have different timing origins, and extracting the intended frame isn't always as straightforward as seeking to a number. (&lt;strong&gt;&lt;em&gt;Literal pain&lt;/em&gt;&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  A quick look at the five tools
  &lt;ul&gt;
&lt;li&gt;
&lt;code&gt;inspect_video&lt;/code&gt; opens a video and returns its source metadata, duration, and available caption tracks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search_transcript&lt;/code&gt; searches for literal phrases or terms in a selected caption track.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;read_transcript&lt;/code&gt; retrieves timestamped caption segments from a requested interval.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_overview&lt;/code&gt; provides up to 12 sampled images to help navigate a video.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_frames&lt;/code&gt; retrieves JPEG frames at specific timestamps, in short bursts, or on a fixed schedule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The host handles video discovery and interpretation. Urma handles evidence retrieval and keeps track of what it returned.&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Urma uses source-provided captions, &lt;em&gt;so videos without captions can't be searched by speech&lt;/em&gt;. It can still retrieve visual evidence when the video source is supported.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying it
&lt;/h2&gt;

&lt;p&gt;Urma runs locally on Windows, macOS, and Linux, with x64 and ARM64 support. It works with Node.js 22.16+ within the 22.x line, as well as Node.js 24 and 26.&lt;/p&gt;

&lt;p&gt;If you use a coding agent that can read GitHub repositories and run commands, you can also point it to Urma's README and ask it to help with setup. Pretty fast actually, provided the agent doesn't decide your entire development environment needs refactoring first.&lt;/p&gt;

&lt;p&gt;Setup installs and verifies the FFmpeg, ffprobe, and yt-dlp components it needs.&lt;/p&gt;

&lt;p&gt;No need to install all three manually or play detective with environment variables. I'd rather people spend their time using Urma than figuring out which FFmpeg binary Windows has decided to use today ;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; urma-mcp@latest setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once setup finishes, connect Urma to your MCP host and restart the host. The README covers the configuration and has examples of the tool arguments.&lt;/p&gt;

&lt;p&gt;You can use public video URLs that pass Urma's source checks, or local files in directories you've explicitly allowed. Remote support depends on the video provider and its available formats, so some sources may not work.&lt;/p&gt;

&lt;p&gt;Here's the repository if you want to look through the code or try it yourself:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sajidurdev" rel="noopener noreferrer"&gt;
        sajidurdev
      &lt;/a&gt; / &lt;a href="https://github.com/sajidurdev/urma" rel="noopener noreferrer"&gt;
        urma
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Retrieve video captions and frames through a local MCP server.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Urma&lt;/h1&gt;
&lt;/div&gt;

&lt;div&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/sajidurdev/urma/main/assets/urma-banner.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fsajidurdev%2Furma%2Fmain%2Fassets%2Furma-banner.png" alt="Urma" width="100%"&gt;&lt;/a&gt;
  &lt;br&gt;&lt;br&gt;
  &lt;strong&gt;Retrieve video captions and frames through MCP.&lt;/strong&gt;
  &lt;br&gt;&lt;br&gt;
  &lt;a href="https://github.com/sajidurdev/urma#try-urma" rel="noopener noreferrer"&gt;Try Urma&lt;/a&gt;
  ·
  &lt;a href="https://github.com/sajidurdev/urma#install-and-connect-a-host" rel="noopener noreferrer"&gt;Install&lt;/a&gt;
  ·
  &lt;a href="https://github.com/sajidurdev/urma#tools" rel="noopener noreferrer"&gt;Tools&lt;/a&gt;
  ·
  &lt;a href="https://github.com/sajidurdev/urma#configuration" rel="noopener noreferrer"&gt;Configuration&lt;/a&gt;
  ·
  &lt;a href="https://github.com/sajidurdev/urma#documentation" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;
  &lt;br&gt;&lt;br&gt;
  &lt;code&gt;urma-mcp&lt;/code&gt; · MCP stdio · Node.js 22.16+ (22.x), 24.x, 26.x
&lt;/div&gt;



&lt;p&gt;Urma gives MCP clients access to captions and frames from public video URLs
and local video files. Search captions for a topic, browse a visual overview
or retrieve frames at specific timestamps.&lt;/p&gt;
&lt;p&gt;Urma runs locally and keeps its cache on your filesystem. Your MCP client
starts the server over stdio and receives the requested text and images
Remote videos require network access.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Try Urma&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Install with &lt;code&gt;npx -y urma-mcp@latest setup&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sajidurdev/urma#register-a-generic-json-host" rel="noopener noreferrer"&gt;Connect your MCP client&lt;/a&gt; and restart it.&lt;/li&gt;
&lt;li&gt;Give the client a video URL and a question about the video.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example, replace &lt;code&gt;&amp;lt;video URL&amp;gt;&lt;/code&gt; in this prompt with a public product demo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In this demo, where does the presenter discuss dark mode, and is the toggle
enabled on screen? &lt;code&gt;&amp;lt;video URL&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/sajidurdev/urma" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It's written in TypeScript, runs as a local stdio MCP server, and is available under the Apache-2.0 license.&lt;/p&gt;

&lt;p&gt;I'd be interested in hearing how it works with different MCP hosts. If you run into trouble with a video source, setup, or frame retrieval, feel free to open an issue. Those are especially useful to test outside my own environment.&lt;/p&gt;

&lt;p&gt;And if you find a video that breaks Urma, please include the URL and what went wrong. A reproducible bug report is always appreciated. My collection of mysterious failures is big enough already.&lt;/p&gt;

&lt;p&gt;Thanks for reading my first DEV post! :)&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>opensource</category>
      <category>mcp</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
