video-context-mcp-server 1.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +380 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -0
- package/dist/services/ffmpeg.d.ts +47 -0
- package/dist/services/ffmpeg.d.ts.map +1 -0
- package/dist/services/ffmpeg.js +170 -0
- package/dist/services/ffmpeg.js.map +1 -0
- package/dist/services/geminiClient.d.ts +47 -0
- package/dist/services/geminiClient.d.ts.map +1 -0
- package/dist/services/geminiClient.js +130 -0
- package/dist/services/geminiClient.js.map +1 -0
- package/dist/services/glmClient.d.ts +50 -0
- package/dist/services/glmClient.d.ts.map +1 -0
- package/dist/services/glmClient.js +196 -0
- package/dist/services/glmClient.js.map +1 -0
- package/dist/services/kimiClient.d.ts +45 -0
- package/dist/services/kimiClient.d.ts.map +1 -0
- package/dist/services/kimiClient.js +152 -0
- package/dist/services/kimiClient.js.map +1 -0
- package/dist/services/providerRouter.d.ts +30 -0
- package/dist/services/providerRouter.d.ts.map +1 -0
- package/dist/services/providerRouter.js +62 -0
- package/dist/services/providerRouter.js.map +1 -0
- package/dist/tools/analyzeVideo.d.ts +18 -0
- package/dist/tools/analyzeVideo.d.ts.map +1 -0
- package/dist/tools/analyzeVideo.js +118 -0
- package/dist/tools/analyzeVideo.js.map +1 -0
- package/dist/tools/extractFrames.d.ts +22 -0
- package/dist/tools/extractFrames.d.ts.map +1 -0
- package/dist/tools/extractFrames.js +82 -0
- package/dist/tools/extractFrames.js.map +1 -0
- package/dist/tools/getVideoInfo.d.ts +18 -0
- package/dist/tools/getVideoInfo.d.ts.map +1 -0
- package/dist/tools/getVideoInfo.js +52 -0
- package/dist/tools/getVideoInfo.js.map +1 -0
- package/dist/tools/searchTimestamp.d.ts +25 -0
- package/dist/tools/searchTimestamp.d.ts.map +1 -0
- package/dist/tools/searchTimestamp.js +146 -0
- package/dist/tools/searchTimestamp.js.map +1 -0
- package/dist/tools/summarizeVideo.d.ts +18 -0
- package/dist/tools/summarizeVideo.d.ts.map +1 -0
- package/dist/tools/summarizeVideo.js +159 -0
- package/dist/tools/summarizeVideo.js.map +1 -0
- package/dist/utils/base64.d.ts +35 -0
- package/dist/utils/base64.d.ts.map +1 -0
- package/dist/utils/base64.js +50 -0
- package/dist/utils/base64.js.map +1 -0
- package/dist/utils/logger.d.ts +23 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +34 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/tempFiles.d.ts +20 -0
- package/dist/utils/tempFiles.d.ts.map +1 -0
- package/dist/utils/tempFiles.js +31 -0
- package/dist/utils/tempFiles.js.map +1 -0
- package/dist/utils/videoUtils.d.ts +19 -0
- package/dist/utils/videoUtils.d.ts.map +1 -0
- package/dist/utils/videoUtils.js +38 -0
- package/dist/utils/videoUtils.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
# Video Context MCP Server
|
|
2
|
+
|
|
3
|
+
Video Context MCP Server is a Model Context Protocol (MCP) server that gives MCP-compatible coding assistants (such as GitHub Copilot in VS Code, Cursor, and Claude Code) the ability to understand and analyze video content. Supports three AI backends: **Gemini 3 Flash Preview** (Google), **Kimi K2.5** (Moonshot AI), and **GLM-4.6V** (Z.AI).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎬 **Video Q&A** — Ask questions about video content and get AI-powered answers
|
|
8
|
+
- 📝 **Video Summarization** — Generate structured summaries with key scenes and timelines
|
|
9
|
+
- 🖼️ **Frame Extraction** — Extract frames at specific timestamps or intervals
|
|
10
|
+
- 🔍 **Timestamp Search** — Find the exact moment when something happens in a video
|
|
11
|
+
- 📊 **Video Metadata** — Get duration, resolution, fps, codec, and other technical details
|
|
12
|
+
- 🔄 **Multi-Backend Support** — Choose between Gemini (native multimodal), GLM-4.6V (cheap/free), or Kimi K2.5 (broader format support)
|
|
13
|
+
- 🎯 **Smart Video Handling** — Extracts keyframes from long videos to reduce token usage (when not using Gemini)
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### Quick Start (Recommended for ordinary users)
|
|
18
|
+
|
|
19
|
+
#### 1. Prerequisites
|
|
20
|
+
|
|
21
|
+
- Node.js 18+
|
|
22
|
+
- VS Code with GitHub Copilot Chat enabled
|
|
23
|
+
|
|
24
|
+
#### 2. Get API keys
|
|
25
|
+
|
|
26
|
+
You'll need API keys for one or more backends:
|
|
27
|
+
|
|
28
|
+
- **Gemini 3 Flash Preview (Google)**: [Get API Key](https://aistudio.google.com/app/apikey)
|
|
29
|
+
- **Kimi K2.5 (Moonshot AI)**: [Get API Key](https://platform.moonshot.ai)
|
|
30
|
+
- **GLM-4.6V (Z.AI)**: [Get API Key](https://z.ai/manage-apikey/apikey-list)
|
|
31
|
+
|
|
32
|
+
#### 3. Install the MCP server
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g video-context-mcp-server
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This installs the executable command: `video-context-mcp`.
|
|
39
|
+
|
|
40
|
+
> **Tip:** Periodically re-run the above command to get the latest version:
|
|
41
|
+
>
|
|
42
|
+
> ```bash
|
|
43
|
+
> npm install -g video-context-mcp-server@latest
|
|
44
|
+
> ```
|
|
45
|
+
|
|
46
|
+
#### 4. Configure VS Code MCP
|
|
47
|
+
|
|
48
|
+
Create (or update) `.vscode/mcp.json` in your project/workspace:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"servers": {
|
|
53
|
+
"videoMcp": {
|
|
54
|
+
"type": "stdio",
|
|
55
|
+
"command": "video-context-mcp",
|
|
56
|
+
"env": {
|
|
57
|
+
"GEMINI_API_KEY": "your-gemini-key",
|
|
58
|
+
"MOONSHOT_API_KEY": "your-moonshot-key",
|
|
59
|
+
"Z_AI_API_KEY": "your-zai-key"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Open Copilot Chat in VS Code. The MCP server starts automatically when tools are needed.
|
|
67
|
+
|
|
68
|
+
### Configure Cursor MCP
|
|
69
|
+
|
|
70
|
+
Add this server to your Cursor MCP configuration (global or project-level):
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"videoMcp": {
|
|
76
|
+
"command": "video-context-mcp",
|
|
77
|
+
"env": {
|
|
78
|
+
"GEMINI_API_KEY": "your-gemini-key",
|
|
79
|
+
"MOONSHOT_API_KEY": "your-moonshot-key",
|
|
80
|
+
"Z_AI_API_KEY": "your-zai-key"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Notes:
|
|
88
|
+
|
|
89
|
+
- Run `npm install -g video-context-mcp-server` first if you haven't already.
|
|
90
|
+
- If you prefer not to install globally, use `npx -y video-context-mcp-server@latest` as the command (slower startup due to registry check).
|
|
91
|
+
- Set one or both API keys depending on which provider you use.
|
|
92
|
+
|
|
93
|
+
### Configure Claude Code MCP
|
|
94
|
+
|
|
95
|
+
Use the Claude CLI to register the MCP server:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
claude mcp add videoMcp video-context-mcp \
|
|
99
|
+
--env GEMINI_API_KEY=your-gemini-key \
|
|
100
|
+
--env MOONSHOT_API_KEY=your-moonshot-key \
|
|
101
|
+
--env Z_AI_API_KEY=your-zai-key
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then verify with:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
claude mcp list
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If you prefer not to install globally, register via `npx` instead (slower startup due to registry check):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
claude mcp add videoMcp npx -y video-context-mcp-server@latest \
|
|
114
|
+
--env MOONSHOT_API_KEY=your-moonshot-key \
|
|
115
|
+
--env Z_AI_API_KEY=your-zai-key
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Troubleshooting Setup
|
|
119
|
+
|
|
120
|
+
- **`video-context-mcp: command not found`**
|
|
121
|
+
- Make sure Node.js is installed and available in your shell (`node -v`, `npm -v`).
|
|
122
|
+
- If installed globally, re-run: `npm install -g video-context-mcp-server`.
|
|
123
|
+
- If global binaries are not on PATH, use `npx -y video-context-mcp-server@latest` instead of `video-context-mcp`.
|
|
124
|
+
|
|
125
|
+
- **MCP server not appearing in client**
|
|
126
|
+
- Restart the client app after changing MCP configuration.
|
|
127
|
+
- Validate JSON syntax in your MCP config file.
|
|
128
|
+
- For Claude Code, verify registration with `claude mcp list`.
|
|
129
|
+
|
|
130
|
+
- **Missing API key errors**
|
|
131
|
+
- Set `GEMINI_API_KEY` for Gemini usage, `Z_AI_API_KEY` for GLM usage, and `MOONSHOT_API_KEY` for Kimi usage.
|
|
132
|
+
- You can set only one key if you only use one provider.
|
|
133
|
+
- For local files, if `provider=gemini` is requested but `GEMINI_API_KEY` is missing, the server automatically falls back to GLM (and then Kimi) when those keys are available.
|
|
134
|
+
- For remote `http(s)` video URLs, use `provider=gemini` or `provider=glm` (Kimi requires local file input). Gemini will automatically download the remote video to a temporary file before processing.
|
|
135
|
+
|
|
136
|
+
### Alternative: Run via npx without global install
|
|
137
|
+
|
|
138
|
+
If you prefer not to install globally, you can use `npx` instead. Note this adds a startup delay due to the npm registry check on each run:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"servers": {
|
|
143
|
+
"videoMcp": {
|
|
144
|
+
"type": "stdio",
|
|
145
|
+
"command": "npx",
|
|
146
|
+
"args": ["-y", "video-context-mcp-server@latest"],
|
|
147
|
+
"env": {
|
|
148
|
+
"GEMINI_API_KEY": "your-gemini-key",
|
|
149
|
+
"MOONSHOT_API_KEY": "your-moonshot-key",
|
|
150
|
+
"Z_AI_API_KEY": "your-zai-key"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The `@latest` tag ensures you always get the newest published version, at the cost of a network round-trip on every startup — this also means the `npx` approach self-updates automatically and requires no manual update step.
|
|
158
|
+
|
|
159
|
+
### For contributors: install from source
|
|
160
|
+
|
|
161
|
+
Clone this repository, then:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npm install
|
|
165
|
+
npm run build
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Then use this `.vscode/mcp.json` server command:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"servers": {
|
|
173
|
+
"videoMcp": {
|
|
174
|
+
"type": "stdio",
|
|
175
|
+
"command": "node",
|
|
176
|
+
"args": ["${workspaceFolder}/dist/index.js"],
|
|
177
|
+
"env": {
|
|
178
|
+
"GEMINI_API_KEY": "your-gemini-key",
|
|
179
|
+
"MOONSHOT_API_KEY": "your-moonshot-key",
|
|
180
|
+
"Z_AI_API_KEY": "your-zai-key"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Debugging Behavior in VS Code
|
|
188
|
+
|
|
189
|
+
When your `.vscode/mcp.json` includes a `dev` block such as:
|
|
190
|
+
|
|
191
|
+
```jsonc
|
|
192
|
+
{
|
|
193
|
+
"servers": {
|
|
194
|
+
"videoMcp": {
|
|
195
|
+
"type": "stdio",
|
|
196
|
+
"command": "node",
|
|
197
|
+
"args": ["${workspaceFolder}/dist/index.js"],
|
|
198
|
+
"env": {
|
|
199
|
+
"GEMINI_API_KEY": "your-gemini-key",
|
|
200
|
+
"MOONSHOT_API_KEY": "your-moonshot-key",
|
|
201
|
+
"Z_AI_API_KEY": "your-zai-key",
|
|
202
|
+
},
|
|
203
|
+
"dev": {
|
|
204
|
+
"watch": "src/**/*.ts",
|
|
205
|
+
"debug": { "type": "node" },
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
you may see frequent logs in the **Output** panel under `MCP: videoMcp`.
|
|
213
|
+
|
|
214
|
+
This is expected in development mode:
|
|
215
|
+
|
|
216
|
+
- `watch` restarts/reloads the MCP server when TypeScript files change
|
|
217
|
+
- `debug` enables Node debug integration
|
|
218
|
+
- MCP protocol payloads (tool schemas, discovery events, lifecycle messages) are printed in that output channel
|
|
219
|
+
|
|
220
|
+
If you want less noise, remove either:
|
|
221
|
+
|
|
222
|
+
- `dev.debug` (keeps auto-watch, disables debug integration), or
|
|
223
|
+
- the full `dev` block (disables watch + debug behavior)
|
|
224
|
+
|
|
225
|
+
## Available Tools
|
|
226
|
+
|
|
227
|
+
| Tool | Description | Parameters |
|
|
228
|
+
| ------------------ | ------------------------------------ | --------------------------------------------------- |
|
|
229
|
+
| `analyze_video` | Ask questions about video content | `videoPath`, `question`, `provider?` |
|
|
230
|
+
| `summarize_video` | Generate a structured video summary | `videoPath`, `provider?` |
|
|
231
|
+
| `extract_frames` | Extract frames from a video | `videoPath`, `mode`, `count/intervalSec/timestamps` |
|
|
232
|
+
| `search_timestamp` | Find when something specific happens | `videoPath`, `query`, `provider?` |
|
|
233
|
+
| `get_video_info` | Get video metadata | `videoPath` |
|
|
234
|
+
|
|
235
|
+
### Path and Provider Constraints
|
|
236
|
+
|
|
237
|
+
- `analyze_video` and `summarize_video` support local files and `http(s)` URLs.
|
|
238
|
+
- For remote `http(s)` URLs, `provider=gemini` and `provider=glm` are supported. `provider=kimi` requires a local file.
|
|
239
|
+
- `search_timestamp`, `extract_frames`, and `get_video_info` currently support local files only.
|
|
240
|
+
- For local inputs, `analyze_video`, `summarize_video`, and `search_timestamp` accept normal paths or `file://` URIs.
|
|
241
|
+
- `extract_frames` and `get_video_info` currently expect local filesystem path strings.
|
|
242
|
+
|
|
243
|
+
## Usage Examples
|
|
244
|
+
|
|
245
|
+
### Analyze Video
|
|
246
|
+
|
|
247
|
+
Ask Copilot Chat:
|
|
248
|
+
|
|
249
|
+
> "Analyze the video at `./demo.mp4` and tell me what happens in it"
|
|
250
|
+
|
|
251
|
+
### Summarize Video
|
|
252
|
+
|
|
253
|
+
> "Summarize the video at `./long-video.mp4`"
|
|
254
|
+
|
|
255
|
+
### Extract Frames
|
|
256
|
+
|
|
257
|
+
> "Extract 5 evenly-spaced frames from `./video.mp4`"
|
|
258
|
+
|
|
259
|
+
> "Extract a frame at timestamp 30 seconds from `./video.mp4`"
|
|
260
|
+
|
|
261
|
+
### Search Timestamp
|
|
262
|
+
|
|
263
|
+
> "In `./video.mp4`, at what timestamp does the person wave?"
|
|
264
|
+
|
|
265
|
+
### Get Video Info
|
|
266
|
+
|
|
267
|
+
> "Get the video info for `./video.mp4`"
|
|
268
|
+
|
|
269
|
+
## Additional Guides
|
|
270
|
+
|
|
271
|
+
- [Screen Recording for Small File Sizes (Windows)](docs/screen-recording-small-files.md)
|
|
272
|
+
|
|
273
|
+
## Backend Comparison
|
|
274
|
+
|
|
275
|
+
| Feature | Gemini 3 Flash Preview | GLM-4.6V | Kimi K2.5 |
|
|
276
|
+
| -------------- | ---------------------------------------------- | ------------------------------ | ---------------------------------------------- |
|
|
277
|
+
| Video formats | mp4, mpeg, mov, avi, flv, mpg, webm, wmv, 3gpp | mp4, avi, mov, wmv, webm, m4v | mp4, mpeg, mov, avi, flv, mpg, webm, wmv, 3gpp |
|
|
278
|
+
| Price | Free tier available | $0.30 input / $0.90 output | $0.60 input / $3.00 output |
|
|
279
|
+
| Free tier | Yes | Yes (GLM-4.6V-Flash) | No |
|
|
280
|
+
| Context window | 1M tokens | 128K | 256K |
|
|
281
|
+
| Max file size | 2 GB | ~20 MB (base64) | 100 MB |
|
|
282
|
+
| Best for | Fallback only (inaccurate despite features) | **Default**, accurate analysis | Paid fallback |
|
|
283
|
+
|
|
284
|
+
**GLM-4.6V is the default backend** — it provides the most accurate video analysis results. While Gemini 3 Flash Preview offers superior features (1M token context, 2GB file size, native multimodal audio+video support), it has **proven inaccurate for video content analysis** in practice. Use Kimi K2.5 as the **first fallback** when GLM is unavailable, and Gemini as the **last resort fallback**. Set `VIDEO_MCP_DEFAULT_PROVIDER=kimi` or `VIDEO_MCP_DEFAULT_PROVIDER=gemini` to switch the default. This env default is used when a tool call omits the `provider` parameter.
|
|
285
|
+
|
|
286
|
+
## Environment Variables
|
|
287
|
+
|
|
288
|
+
| Variable | Description | Required |
|
|
289
|
+
| ---------------------------- | -------------------------------------------- | ---------------------------------------- |
|
|
290
|
+
| `GEMINI_API_KEY` | Google API key for Gemini 3 Flash Preview | Optional (required if using Gemini) |
|
|
291
|
+
| `MOONSHOT_API_KEY` | Moonshot AI API key for Kimi K2.5 | Optional (required if using Kimi) |
|
|
292
|
+
| `Z_AI_API_KEY` | Z.AI API key for GLM-4.6V | Optional (required if using GLM) |
|
|
293
|
+
| `VIDEO_MCP_DEFAULT_PROVIDER` | Default backend (`gemini`, `glm`, `kimi`) | Optional (default: `glm`) |
|
|
294
|
+
| `VIDEO_MCP_MAX_FRAMES` | Max frames for summarization (GLM/Kimi only) | Optional (default: 20; clamped to 5-100) |
|
|
295
|
+
|
|
296
|
+
### Example Configuration
|
|
297
|
+
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"servers": {
|
|
301
|
+
"videoMcp": {
|
|
302
|
+
"type": "stdio",
|
|
303
|
+
"command": "video-context-mcp",
|
|
304
|
+
"env": {
|
|
305
|
+
"GEMINI_API_KEY": "your-gemini-key",
|
|
306
|
+
"Z_AI_API_KEY": "your-zai-key",
|
|
307
|
+
"MOONSHOT_API_KEY": "your-moonshot-key",
|
|
308
|
+
"VIDEO_MCP_DEFAULT_PROVIDER": "glm"
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
> **Note:** `VIDEO_MCP_MAX_FRAMES` only applies when using **GLM or Kimi** as the provider. Gemini uploads the full video natively and ignores this setting. Add it to `env` only if you are running with `VIDEO_MCP_DEFAULT_PROVIDER=gemini`.
|
|
316
|
+
|
|
317
|
+
## Development
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Install dependencies
|
|
321
|
+
npm install
|
|
322
|
+
|
|
323
|
+
# Run in development (auto-restart on changes)
|
|
324
|
+
npm run dev
|
|
325
|
+
|
|
326
|
+
# Build for production
|
|
327
|
+
npm run build
|
|
328
|
+
|
|
329
|
+
# Run type checking
|
|
330
|
+
npm run type-check
|
|
331
|
+
|
|
332
|
+
# Run linter
|
|
333
|
+
npm run lint
|
|
334
|
+
|
|
335
|
+
# Run automated tests
|
|
336
|
+
npm run test
|
|
337
|
+
|
|
338
|
+
# Run tests in watch mode
|
|
339
|
+
npm run test:watch
|
|
340
|
+
|
|
341
|
+
# Run tests with coverage
|
|
342
|
+
npm run test:coverage
|
|
343
|
+
|
|
344
|
+
# Format all files
|
|
345
|
+
npm run format
|
|
346
|
+
|
|
347
|
+
# Check formatting only
|
|
348
|
+
npm run format:check
|
|
349
|
+
|
|
350
|
+
# Lint + Type-check + Format + Build
|
|
351
|
+
npm run ltfb
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Architecture
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
video-mcp/
|
|
358
|
+
├── src/
|
|
359
|
+
│ ├── index.ts # MCP server entry point
|
|
360
|
+
│ ├── tools/ # MCP tool implementations
|
|
361
|
+
│ ├── services/ # Backend clients (Kimi, GLM, ffmpeg)
|
|
362
|
+
│ └── utils/ # Helpers (temp files, base64)
|
|
363
|
+
├── .vscode/
|
|
364
|
+
│ └── mcp.json # VS Code MCP configuration
|
|
365
|
+
├── docs/
|
|
366
|
+
│ └── technical/ # Technical documentation
|
|
367
|
+
└── .github/
|
|
368
|
+
└── copilot-instructions.md # Copilot AI assistant guidelines
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## License
|
|
372
|
+
|
|
373
|
+
MIT
|
|
374
|
+
|
|
375
|
+
## Credits
|
|
376
|
+
|
|
377
|
+
- [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) by Anthropic
|
|
378
|
+
- [Kimi K2.5](https://github.com/MoonshotAI/Kimi-K2.5) by Moonshot AI
|
|
379
|
+
- [GLM-4.6V](https://docs.z.ai/guides/vlm/glm-4.6v) by Z.AI
|
|
380
|
+
- [ffmpeg](https://ffmpeg.org/) for video processing
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
// Import tool handlers
|
|
6
|
+
import { analyzeVideoTool } from './tools/analyzeVideo.js';
|
|
7
|
+
import { summarizeVideoTool } from './tools/summarizeVideo.js';
|
|
8
|
+
import { extractFramesTool } from './tools/extractFrames.js';
|
|
9
|
+
import { searchTimestampTool } from './tools/searchTimestamp.js';
|
|
10
|
+
import { getVideoInfoTool } from './tools/getVideoInfo.js';
|
|
11
|
+
import { setLoggerServer } from './utils/logger.js';
|
|
12
|
+
/**
|
|
13
|
+
* Main entry point for the Video Context MCP Server
|
|
14
|
+
* Creates an MCP server, registers all video analysis tools, and connects via stdio
|
|
15
|
+
*/
|
|
16
|
+
async function main() {
|
|
17
|
+
// Create MCP server with name and version
|
|
18
|
+
const server = new McpServer({
|
|
19
|
+
name: 'video-mcp',
|
|
20
|
+
version: '1.0.0',
|
|
21
|
+
}, {
|
|
22
|
+
capabilities: {
|
|
23
|
+
logging: {}, // Enable logging for progress reporting
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
// Wire up the logger so tools can emit progress notifications
|
|
27
|
+
setLoggerServer(server);
|
|
28
|
+
// Register all video analysis tools
|
|
29
|
+
// Tool 1: analyze_video - Ask questions about video content
|
|
30
|
+
server.registerTool('analyze_video', {
|
|
31
|
+
title: 'Analyze Video',
|
|
32
|
+
description: 'Ask questions about video content and get AI-powered answers. Supports both local files and URLs.',
|
|
33
|
+
inputSchema: z.object({
|
|
34
|
+
videoPath: z
|
|
35
|
+
.string()
|
|
36
|
+
.describe('Path to the video file (local path or URL)'),
|
|
37
|
+
question: z
|
|
38
|
+
.string()
|
|
39
|
+
.describe('Question to ask about the video content'),
|
|
40
|
+
provider: z
|
|
41
|
+
.enum(['glm', 'kimi', 'gemini'])
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("AI backend to use: 'glm' (GLM-4.6V, default), 'kimi' (Kimi K2.5), or 'gemini' (Gemini 3 Flash Preview)"),
|
|
44
|
+
}),
|
|
45
|
+
}, analyzeVideoTool);
|
|
46
|
+
// Tool 2: summarize_video - Generate structured video summary
|
|
47
|
+
server.registerTool('summarize_video', {
|
|
48
|
+
title: 'Summarize Video',
|
|
49
|
+
description: 'Generate a structured summary of the video including overview, key scenes, and timeline. For long videos (>5 min), extracts keyframes to reduce token usage (unless using Gemini, which processes natively).',
|
|
50
|
+
inputSchema: z.object({
|
|
51
|
+
videoPath: z
|
|
52
|
+
.string()
|
|
53
|
+
.describe('Path to the video file (local path or URL)'),
|
|
54
|
+
provider: z
|
|
55
|
+
.enum(['glm', 'kimi', 'gemini'])
|
|
56
|
+
.optional()
|
|
57
|
+
.describe("AI backend to use: 'glm' (GLM-4.6V, default), 'kimi' (Kimi K2.5), or 'gemini' (Gemini 3 Flash Preview)"),
|
|
58
|
+
}),
|
|
59
|
+
}, summarizeVideoTool);
|
|
60
|
+
// Tool 3: extract_frames - Extract frames from video
|
|
61
|
+
server.registerTool('extract_frames', {
|
|
62
|
+
title: 'Extract Frames',
|
|
63
|
+
description: 'Extract frames from a video at specific timestamps or intervals. Supports local files (including file:// URIs) and remote http(s) URLs. No AI backend required.',
|
|
64
|
+
inputSchema: z.object({
|
|
65
|
+
videoPath: z
|
|
66
|
+
.string()
|
|
67
|
+
.describe('Path to the video file (local path, file:// URI, or http(s) URL)'),
|
|
68
|
+
mode: z
|
|
69
|
+
.enum(['even', 'interval', 'timestamps'])
|
|
70
|
+
.describe("Extraction mode: 'even' (N evenly-spaced frames), 'interval' (every N seconds), or 'timestamps' (at specific times)"),
|
|
71
|
+
count: z
|
|
72
|
+
.number()
|
|
73
|
+
.int()
|
|
74
|
+
.min(1)
|
|
75
|
+
.max(100)
|
|
76
|
+
.optional()
|
|
77
|
+
.describe("Number of frames to extract (required for 'even' mode)"),
|
|
78
|
+
intervalSec: z
|
|
79
|
+
.number()
|
|
80
|
+
.min(0.1)
|
|
81
|
+
.optional()
|
|
82
|
+
.describe("Interval in seconds between frames (required for 'interval' mode)"),
|
|
83
|
+
timestamps: z
|
|
84
|
+
.array(z.number().min(0))
|
|
85
|
+
.optional()
|
|
86
|
+
.describe("Array of timestamps in seconds (required for 'timestamps' mode)"),
|
|
87
|
+
}),
|
|
88
|
+
}, extractFramesTool);
|
|
89
|
+
// Tool 4: search_timestamp - Find when something happens in video
|
|
90
|
+
server.registerTool('search_timestamp', {
|
|
91
|
+
title: 'Search Timestamp',
|
|
92
|
+
description: 'Find the timestamp when something specific happens in a video. Extracts frames and uses AI to locate the content. Supports local files (including file:// URIs) and remote http(s) URLs.',
|
|
93
|
+
inputSchema: z.object({
|
|
94
|
+
videoPath: z
|
|
95
|
+
.string()
|
|
96
|
+
.describe('Path to the video file (local path, file:// URI, or http(s) URL)'),
|
|
97
|
+
query: z
|
|
98
|
+
.string()
|
|
99
|
+
.describe("What to search for, e.g., 'person waves', 'dog runs', 'car crash'"),
|
|
100
|
+
provider: z
|
|
101
|
+
.enum(['glm', 'kimi', 'gemini'])
|
|
102
|
+
.optional()
|
|
103
|
+
.describe("AI backend to use: 'glm' (GLM-4.6V, default), 'kimi' (Kimi K2.5), or 'gemini' (Gemini 3 Flash Preview)"),
|
|
104
|
+
}),
|
|
105
|
+
}, searchTimestampTool);
|
|
106
|
+
// Tool 5: get_video_info - Get video metadata
|
|
107
|
+
server.registerTool('get_video_info', {
|
|
108
|
+
title: 'Get Video Info',
|
|
109
|
+
description: 'Get video metadata including duration, resolution, fps, codec, file size, and format. Supports local files (including file:// URIs) and remote http(s) URLs. No AI backend required.',
|
|
110
|
+
inputSchema: z.object({
|
|
111
|
+
videoPath: z
|
|
112
|
+
.string()
|
|
113
|
+
.describe('Path to the video file (local path, file:// URI, or http(s) URL)'),
|
|
114
|
+
}),
|
|
115
|
+
}, getVideoInfoTool);
|
|
116
|
+
// Connect to VS Code via stdio transport
|
|
117
|
+
const transport = new StdioServerTransport();
|
|
118
|
+
await server.connect(transport);
|
|
119
|
+
// Server is now running, listening for tool calls from Copilot
|
|
120
|
+
}
|
|
121
|
+
main().catch((error) => {
|
|
122
|
+
console.error('Fatal error starting video-mcp server:', error);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video Metadata
|
|
3
|
+
*/
|
|
4
|
+
export interface VideoMetadata {
|
|
5
|
+
duration: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
fps: number;
|
|
9
|
+
codec: string;
|
|
10
|
+
fileSize: number;
|
|
11
|
+
format: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get video metadata using ffprobe
|
|
15
|
+
* @param videoPath - Path to the video file
|
|
16
|
+
* @returns Video metadata
|
|
17
|
+
*/
|
|
18
|
+
export declare function getVideoMetadata(videoPath: string): Promise<VideoMetadata>;
|
|
19
|
+
/**
|
|
20
|
+
* Extract a single frame at a specific timestamp
|
|
21
|
+
* @param videoPath - Path to the video file
|
|
22
|
+
* @param timestampSec - Timestamp in seconds
|
|
23
|
+
* @returns Buffer containing the PNG frame
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractFrameAt(videoPath: string, timestampSec: number): Promise<Buffer>;
|
|
26
|
+
/**
|
|
27
|
+
* Extract N evenly-spaced frames from a video
|
|
28
|
+
* @param videoPath - Path to the video file
|
|
29
|
+
* @param count - Number of frames to extract
|
|
30
|
+
* @returns Array of PNG buffers
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractFramesEvenly(videoPath: string, count: number): Promise<Buffer[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Extract frames at regular intervals
|
|
35
|
+
* @param videoPath - Path to the video file
|
|
36
|
+
* @param intervalSec - Interval in seconds between frames
|
|
37
|
+
* @returns Array of PNG buffers
|
|
38
|
+
*/
|
|
39
|
+
export declare function extractFramesAtInterval(videoPath: string, intervalSec: number): Promise<Buffer[]>;
|
|
40
|
+
/**
|
|
41
|
+
* Extract frames at specific timestamps
|
|
42
|
+
* @param videoPath - Path to the video file
|
|
43
|
+
* @param timestamps - Array of timestamps in seconds
|
|
44
|
+
* @returns Array of PNG buffers (same order as timestamps)
|
|
45
|
+
*/
|
|
46
|
+
export declare function extractFramesAtTimestamps(videoPath: string, timestamps: number[]): Promise<Buffer[]>;
|
|
47
|
+
//# sourceMappingURL=ffmpeg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ffmpeg.d.ts","sourceRoot":"","sources":["../../src/services/ffmpeg.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CA0BxB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAoBjB;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,EAAE,CAAC,CA6BnB;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBnB;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BnB"}
|