mcp-video-analyzer 0.2.2 → 0.2.3

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.
@@ -1,4 +1,4 @@
1
- import type { ITranscriptEntry, IVideoMetadata, IVideoComment, IChapter, IAdapterCapabilities } from '../types.js';
1
+ import type { IAdapterCapabilities, IChapter, ITranscriptEntry, IVideoComment, IVideoMetadata } from '../types.js';
2
2
  export interface IVideoAdapter {
3
3
  readonly name: string;
4
4
  readonly capabilities: IAdapterCapabilities;
@@ -1,4 +1,4 @@
1
- import type { ITranscriptEntry, IVideoMetadata, IVideoComment, IChapter, IAdapterCapabilities } from '../types.js';
1
+ import type { IAdapterCapabilities, IChapter, ITranscriptEntry, IVideoComment, IVideoMetadata } from '../types.js';
2
2
  import type { IVideoAdapter } from './adapter.interface.js';
3
3
  export declare class DirectAdapter implements IVideoAdapter {
4
4
  readonly name = "direct";
@@ -1,7 +1,7 @@
1
1
  import { createWriteStream } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import { pipeline } from 'node:stream/promises';
4
3
  import { Readable } from 'node:stream';
4
+ import { pipeline } from 'node:stream/promises';
5
5
  import { detectPlatform } from '../utils/url-detector.js';
6
6
  function getFilenameFromUrl(url) {
7
7
  try {
@@ -1,4 +1,4 @@
1
- import type { ITranscriptEntry, IVideoMetadata, IVideoComment, IChapter, IAdapterCapabilities } from '../types.js';
1
+ import type { IAdapterCapabilities, IChapter, ITranscriptEntry, IVideoComment, IVideoMetadata } from '../types.js';
2
2
  import type { IVideoAdapter } from './adapter.interface.js';
3
3
  export declare class LoomAdapter implements IVideoAdapter {
4
4
  readonly name = "loom";
@@ -1,9 +1,9 @@
1
1
  import { execFile as execFileCb } from 'node:child_process';
2
- import { promisify } from 'node:util';
2
+ import { createWriteStream, existsSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
- import { existsSync, createWriteStream } from 'node:fs';
5
- import { pipeline } from 'node:stream/promises';
6
4
  import { Readable } from 'node:stream';
5
+ import { pipeline } from 'node:stream/promises';
6
+ import { promisify } from 'node:util';
7
7
  import { detectPlatform, extractLoomId } from '../utils/url-detector.js';
8
8
  import { parseVtt } from '../utils/vtt-parser.js';
9
9
  const execFile = promisify(execFileCb);
@@ -1,4 +1,4 @@
1
- import type { ITranscriptEntry, IFrameResult } from '../types.js';
1
+ import type { IFrameResult, ITranscriptEntry } from '../types.js';
2
2
  import type { IOcrResult } from './frame-ocr.js';
3
3
  interface ITimelineEntry {
4
4
  time: string;
@@ -1,7 +1,7 @@
1
1
  import { execFile as execFileCb } from 'node:child_process';
2
- import { promisify } from 'node:util';
3
- import { join } from 'node:path';
4
2
  import { createRequire } from 'node:module';
3
+ import { join } from 'node:path';
4
+ import { promisify } from 'node:util';
5
5
  import { formatTimestamp } from './frame-extractor.js';
6
6
  const execFile = promisify(execFileCb);
7
7
  const require = createRequire(import.meta.url);
@@ -1,8 +1,8 @@
1
1
  import { execFile as execFileCb } from 'node:child_process';
2
- import { promisify } from 'node:util';
3
- import { join } from 'node:path';
4
2
  import { readdir } from 'node:fs/promises';
5
3
  import { createRequire } from 'node:module';
4
+ import { join } from 'node:path';
5
+ import { promisify } from 'node:util';
6
6
  const execFile = promisify(execFileCb);
7
7
  const require = createRequire(import.meta.url);
8
8
  const ffmpegPath = require('ffmpeg-static');
package/dist/server.js CHANGED
@@ -1,18 +1,18 @@
1
1
  import { FastMCP } from 'fastmcp';
2
2
  import { registerAdapter } from './adapters/adapter.interface.js';
3
- import { LoomAdapter } from './adapters/loom.adapter.js';
4
3
  import { DirectAdapter } from './adapters/direct.adapter.js';
4
+ import { LoomAdapter } from './adapters/loom.adapter.js';
5
+ import { registerAnalyzeMoment } from './tools/analyze-moment.js';
5
6
  import { registerAnalyzeVideo } from './tools/analyze-video.js';
6
7
  import { registerGetFrameAt } from './tools/get-frame-at.js';
7
8
  import { registerGetFrameBurst } from './tools/get-frame-burst.js';
8
- import { registerGetTranscript } from './tools/get-transcript.js';
9
- import { registerGetMetadata } from './tools/get-metadata.js';
10
9
  import { registerGetFrames } from './tools/get-frames.js';
11
- import { registerAnalyzeMoment } from './tools/analyze-moment.js';
10
+ import { registerGetMetadata } from './tools/get-metadata.js';
11
+ import { registerGetTranscript } from './tools/get-transcript.js';
12
12
  export function createServer() {
13
13
  const server = new FastMCP({
14
14
  name: 'mcp-video-analyzer',
15
- version: '0.2.2',
15
+ version: '0.2.3',
16
16
  instructions: `Video analysis MCP server. Extracts transcripts, key frames, metadata, comments, OCR text, and annotated timelines from video URLs.
17
17
 
18
18
  AUTOMATIC BEHAVIOR — Do NOT wait for the user to ask:
@@ -1,10 +1,10 @@
1
- import { imageContent, UserError } from 'fastmcp';
1
+ import { UserError, imageContent } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getAdapter } from '../adapters/adapter.interface.js';
4
- import { extractFrameBurst, parseTimestamp } from '../processors/frame-extractor.js';
4
+ import { buildAnnotatedTimeline } from '../processors/annotated-timeline.js';
5
5
  import { deduplicateFrames } from '../processors/frame-dedup.js';
6
+ import { extractFrameBurst, parseTimestamp } from '../processors/frame-extractor.js';
6
7
  import { extractTextFromFrames } from '../processors/frame-ocr.js';
7
- import { buildAnnotatedTimeline } from '../processors/annotated-timeline.js';
8
8
  import { optimizeFrames } from '../processors/image-optimizer.js';
9
9
  import { createTempDir } from '../utils/temp-files.js';
10
10
  const AnalyzeMomentSchema = z.object({
@@ -1,17 +1,17 @@
1
- import { imageContent, UserError } from 'fastmcp';
1
+ import { UserError, imageContent } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getAdapter } from '../adapters/adapter.interface.js';
4
- import { extractSceneFrames, extractDenseFrames, probeVideoDuration, formatTimestamp, } from '../processors/frame-extractor.js';
4
+ import { getDetailConfig } from '../config/detail-levels.js';
5
+ import { buildAnnotatedTimeline } from '../processors/annotated-timeline.js';
6
+ import { extractAudioTrack, transcribeAudio } from '../processors/audio-transcriber.js';
5
7
  import { extractBrowserFrames, generateTimestamps } from '../processors/browser-frame-extractor.js';
6
8
  import { deduplicateFrames, filterBlackFrames } from '../processors/frame-dedup.js';
9
+ import { extractDenseFrames, extractSceneFrames, formatTimestamp, probeVideoDuration, } from '../processors/frame-extractor.js';
7
10
  import { extractTextFromFrames } from '../processors/frame-ocr.js';
8
- import { buildAnnotatedTimeline } from '../processors/annotated-timeline.js';
9
11
  import { optimizeFrames } from '../processors/image-optimizer.js';
10
- import { extractAudioTrack, transcribeAudio } from '../processors/audio-transcriber.js';
11
- import { createTempDir, cleanupTempDir } from '../utils/temp-files.js';
12
12
  import { AnalysisCache, cacheKey } from '../utils/cache.js';
13
- import { getDetailConfig } from '../config/detail-levels.js';
14
13
  import { filterAnalysisResult } from '../utils/field-filter.js';
14
+ import { cleanupTempDir, createTempDir } from '../utils/temp-files.js';
15
15
  const cache = new AnalysisCache();
16
16
  const ANALYSIS_FIELDS = [
17
17
  'metadata',
@@ -1,8 +1,8 @@
1
- import { imageContent, UserError } from 'fastmcp';
1
+ import { UserError, imageContent } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getAdapter } from '../adapters/adapter.interface.js';
4
- import { extractFrameAt, parseTimestamp } from '../processors/frame-extractor.js';
5
4
  import { extractBrowserFrames } from '../processors/browser-frame-extractor.js';
5
+ import { extractFrameAt, parseTimestamp } from '../processors/frame-extractor.js';
6
6
  import { optimizeFrame } from '../processors/image-optimizer.js';
7
7
  import { createTempDir } from '../utils/temp-files.js';
8
8
  import { getTempFilePath } from '../utils/temp-files.js';
@@ -1,8 +1,8 @@
1
- import { imageContent, UserError } from 'fastmcp';
1
+ import { UserError, imageContent } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getAdapter } from '../adapters/adapter.interface.js';
4
- import { extractFrameBurst, parseTimestamp } from '../processors/frame-extractor.js';
5
4
  import { extractBrowserFrames } from '../processors/browser-frame-extractor.js';
5
+ import { extractFrameBurst, parseTimestamp } from '../processors/frame-extractor.js';
6
6
  import { optimizeFrames } from '../processors/image-optimizer.js';
7
7
  import { createTempDir } from '../utils/temp-files.js';
8
8
  const GetFrameBurstSchema = z.object({
@@ -1,9 +1,9 @@
1
- import { imageContent, UserError } from 'fastmcp';
1
+ import { UserError, imageContent } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getAdapter } from '../adapters/adapter.interface.js';
4
- import { extractSceneFrames, extractDenseFrames, probeVideoDuration, formatTimestamp, } from '../processors/frame-extractor.js';
5
4
  import { extractBrowserFrames, generateTimestamps } from '../processors/browser-frame-extractor.js';
6
5
  import { deduplicateFrames, filterBlackFrames } from '../processors/frame-dedup.js';
6
+ import { extractDenseFrames, extractSceneFrames, formatTimestamp, probeVideoDuration, } from '../processors/frame-extractor.js';
7
7
  import { optimizeFrames } from '../processors/image-optimizer.js';
8
8
  import { createTempDir } from '../utils/temp-files.js';
9
9
  const GetFramesSchema = z.object({
@@ -2,7 +2,7 @@ import { UserError } from 'fastmcp';
2
2
  import { z } from 'zod';
3
3
  import { getAdapter } from '../adapters/adapter.interface.js';
4
4
  import { extractAudioTrack, transcribeAudio } from '../processors/audio-transcriber.js';
5
- import { createTempDir, cleanupTempDir } from '../utils/temp-files.js';
5
+ import { cleanupTempDir, createTempDir } from '../utils/temp-files.js';
6
6
  const GetTranscriptSchema = z.object({
7
7
  url: z.string().url().describe('Video URL (Loom share link or direct mp4/webm URL)'),
8
8
  });
package/package.json CHANGED
@@ -1,81 +1,82 @@
1
- {
2
- "name": "mcp-video-analyzer",
3
- "version": "0.2.2",
4
- "description": "MCP server for video analysis — extracts transcripts, key frames, OCR text, and metadata from video URLs. Supports Loom and direct video files.",
5
- "author": "guimatheus92",
6
- "license": "MIT",
7
- "homepage": "https://github.com/guimatheus92/mcp-video-analyzer#readme",
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/guimatheus92/mcp-video-analyzer.git"
11
- },
12
- "bugs": {
13
- "url": "https://github.com/guimatheus92/mcp-video-analyzer/issues"
14
- },
15
- "bin": {
16
- "mcp-video-analyzer": "./dist/index.js"
17
- },
18
- "main": "./dist/index.js",
19
- "types": "./dist/index.d.ts",
20
- "files": [
21
- "dist"
22
- ],
23
- "type": "module",
24
- "scripts": {
25
- "build": "tsc",
26
- "prepare": "npm run build",
27
- "dev": "npx fastmcp dev src/index.ts",
28
- "inspect": "npx fastmcp inspect src/index.ts",
29
- "lint": "eslint src/",
30
- "lint:fix": "eslint src/ --fix",
31
- "format": "prettier --write \"src/**/*.ts\" \"*.config.*\" \"*.json\"",
32
- "format:check": "prettier --check \"src/**/*.ts\" \"*.config.*\"",
33
- "typecheck": "tsc --noEmit",
34
- "knip": "knip",
35
- "test": "vitest run",
36
- "test:watch": "vitest",
37
- "test:coverage": "vitest run --coverage",
38
- "test:e2e": "vitest run --config vitest.e2e.config.ts",
39
- "check": "npm run format:check && npm run lint && npm run typecheck && npm run knip && npm run test",
40
- "test:smoke": "npm run build && npx tsx scripts/smoke-test.ts",
41
- "verify-package": "npm run build && npx tsx scripts/verify-package.ts",
42
- "prepublishOnly": "npm run check && npm run build"
43
- },
44
- "keywords": [
45
- "mcp",
46
- "model-context-protocol",
47
- "video",
48
- "video-analysis",
49
- "loom",
50
- "transcript",
51
- "frames",
52
- "ocr",
53
- "screen-recording",
54
- "claude",
55
- "ai"
56
- ],
57
- "engines": {
58
- "node": ">=18"
59
- },
60
- "dependencies": {
61
- "cheerio": "^1.2.0",
62
- "fastmcp": "^3.34.0",
63
- "ffmpeg-static": "^5.3.0",
64
- "puppeteer-core": "^24.39.0",
65
- "sharp": "^0.34.5",
66
- "tesseract.js": "^7.0.0",
67
- "zod": "^4.3.6"
68
- },
69
- "devDependencies": {
70
- "@eslint/js": "^10.0.1",
71
- "@types/node": "^25.4.0",
72
- "@vitest/coverage-v8": "^4.0.18",
73
- "eslint": "^10.0.3",
74
- "knip": "^5.86.0",
75
- "prettier": "^3.8.1",
76
- "tsx": "^4.21.0",
77
- "typescript": "^5.9.3",
78
- "typescript-eslint": "^8.57.0",
79
- "vitest": "^4.0.18"
80
- }
81
- }
1
+ {
2
+ "name": "mcp-video-analyzer",
3
+ "version": "0.2.3",
4
+ "description": "MCP server for video analysis — extracts transcripts, key frames, OCR text, and metadata from video URLs. Supports Loom and direct video files.",
5
+ "author": "guimatheus92",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/guimatheus92/mcp-video-analyzer#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/guimatheus92/mcp-video-analyzer.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/guimatheus92/mcp-video-analyzer/issues"
14
+ },
15
+ "bin": {
16
+ "mcp-video-analyzer": "./dist/index.js"
17
+ },
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "type": "module",
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "prepare": "npm run build",
27
+ "dev": "npx fastmcp dev src/index.ts",
28
+ "inspect": "npx fastmcp inspect src/index.ts",
29
+ "lint": "eslint src/ test/ scripts/",
30
+ "lint:fix": "eslint src/ test/ scripts/ --fix",
31
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\" \"*.config.*\" \"*.json\"",
32
+ "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\" \"scripts/**/*.ts\" \"*.config.*\"",
33
+ "typecheck": "tsc --noEmit",
34
+ "knip": "knip",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest",
37
+ "test:coverage": "vitest run --coverage",
38
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
39
+ "check": "npm run format:check && npm run lint && npm run typecheck && npm run knip && npm run test",
40
+ "test:smoke": "npm run build && vitest run --config vitest.smoke.config.ts",
41
+ "verify-package": "npm run build && npx tsx scripts/verify-package.ts",
42
+ "prepublishOnly": "npm run check && npm run build"
43
+ },
44
+ "keywords": [
45
+ "mcp",
46
+ "model-context-protocol",
47
+ "video",
48
+ "video-analysis",
49
+ "loom",
50
+ "transcript",
51
+ "frames",
52
+ "ocr",
53
+ "screen-recording",
54
+ "claude",
55
+ "ai"
56
+ ],
57
+ "engines": {
58
+ "node": ">=18"
59
+ },
60
+ "dependencies": {
61
+ "cheerio": "^1.2.0",
62
+ "fastmcp": "^3.34.0",
63
+ "ffmpeg-static": "^5.3.0",
64
+ "puppeteer-core": "^24.39.0",
65
+ "sharp": "^0.34.5",
66
+ "tesseract.js": "^7.0.0",
67
+ "zod": "^4.3.6"
68
+ },
69
+ "devDependencies": {
70
+ "@eslint/js": "^10.0.1",
71
+ "@trivago/prettier-plugin-sort-imports": "^6.0.2",
72
+ "@types/node": "^25.4.0",
73
+ "@vitest/coverage-v8": "^4.0.18",
74
+ "eslint": "^10.0.3",
75
+ "knip": "^5.86.0",
76
+ "prettier": "^3.8.1",
77
+ "tsx": "^4.21.0",
78
+ "typescript": "^5.9.3",
79
+ "typescript-eslint": "^8.57.0",
80
+ "vitest": "^4.0.18"
81
+ }
82
+ }