@felores/mcp-video 0.5.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.
@@ -0,0 +1,379 @@
1
+ # MCP Development Guide for LLMs
2
+
3
+ This guide provides structured information for LLMs to assist in creating, modifying, and using Model Context Protocol (MCP) servers.
4
+
5
+ ## 1. Core Concepts
6
+
7
+ ### Protocol Overview
8
+ - MCP enables standardized communication between LLM applications and integrations
9
+ - Uses client-server architecture with JSON-RPC 2.0 message format
10
+ - Latest protocol version: 2024-11-05
11
+ - Supports stdio and SSE transports
12
+
13
+ ### Key Components
14
+ 1. **Hosts**: LLM applications that initiate connections (e.g., Claude Desktop)
15
+ 2. **Clients**: Maintain 1:1 connections with servers
16
+ 3. **Servers**: Provide context, tools, and prompts to clients
17
+ 4. **Resources**: File-like data that can be read by clients
18
+ 5. **Tools**: Functions that can be called by the LLM
19
+ 6. **Prompts**: Pre-written templates for specific tasks
20
+
21
+ ## 2. Server Implementation Guidelines
22
+
23
+ ### Server Structure
24
+ 1. Core Server Class:
25
+ ```typescript
26
+ class Server extends Protocol<ServerRequest, ServerNotification, ServerResult> {
27
+ constructor(serverInfo: Implementation, options: ServerOptions)
28
+ // Must implement base protocol methods
29
+ }
30
+ ```
31
+
32
+ 2. Required Capabilities:
33
+ ```typescript
34
+ interface ServerCapabilities {
35
+ experimental?: object;
36
+ logging?: object;
37
+ prompts?: { listChanged?: boolean };
38
+ resources?: {
39
+ subscribe?: boolean;
40
+ listChanged?: boolean
41
+ };
42
+ tools?: { listChanged?: boolean };
43
+ }
44
+ ```
45
+
46
+ ### Essential Implementation Steps
47
+
48
+ 1. **Server Initialization**:
49
+ ```typescript
50
+ const server = new Server(
51
+ {
52
+ name: "your-server-name",
53
+ version: "1.0.0"
54
+ },
55
+ {
56
+ capabilities: {
57
+ // Declare supported capabilities
58
+ resources: {},
59
+ tools: {},
60
+ prompts: {}
61
+ }
62
+ }
63
+ );
64
+ ```
65
+
66
+ 2. **Request Handlers**:
67
+ ```typescript
68
+ // Example tool handler
69
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
70
+ tools: [
71
+ {
72
+ name: "tool-name",
73
+ description: "Tool description",
74
+ inputSchema: {
75
+ type: "object",
76
+ properties: {
77
+ // Define parameters
78
+ }
79
+ }
80
+ }
81
+ ]
82
+ }));
83
+ ```
84
+
85
+ 3. **Transport Setup**:
86
+ ```typescript
87
+ const transport = new StdioServerTransport();
88
+ await server.connect(transport);
89
+ ```
90
+
91
+ ## 3. Core Features Implementation
92
+
93
+ ### Resources
94
+ ```typescript
95
+ interface Resource {
96
+ uri: string;
97
+ name: string;
98
+ description?: string;
99
+ mimeType?: string;
100
+ }
101
+
102
+ // Handler example
103
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
104
+ resources: [
105
+ {
106
+ uri: "custom://resource",
107
+ name: "Resource Name",
108
+ description: "Resource description"
109
+ }
110
+ ]
111
+ }));
112
+ ```
113
+
114
+ ### Tools
115
+ ```typescript
116
+ interface Tool {
117
+ name: string;
118
+ description?: string;
119
+ inputSchema: {
120
+ type: "object";
121
+ properties?: object;
122
+ required?: string[];
123
+ };
124
+ }
125
+
126
+ // Handler example
127
+ server.setRequestHandler(CallToolRequestSchema, async (request) => ({
128
+ content: [
129
+ {
130
+ type: "text",
131
+ text: "Tool execution result"
132
+ }
133
+ ]
134
+ }));
135
+ ```
136
+
137
+ ### Prompts
138
+ ```typescript
139
+ interface Prompt {
140
+ name: string;
141
+ description?: string;
142
+ arguments?: PromptArgument[];
143
+ }
144
+
145
+ // Handler example
146
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => ({
147
+ messages: [
148
+ {
149
+ role: "user",
150
+ content: {
151
+ type: "text",
152
+ text: "Prompt template"
153
+ }
154
+ }
155
+ ]
156
+ }));
157
+ ```
158
+
159
+ ## 4. Best Practices
160
+
161
+ ### Error Handling
162
+ 1. Use appropriate error codes:
163
+ ```typescript
164
+ enum ErrorCode {
165
+ ParseError = -32700,
166
+ InvalidRequest = -32600,
167
+ MethodNotFound = -32601,
168
+ InvalidParams = -32602,
169
+ InternalError = -32603
170
+ }
171
+ ```
172
+
173
+ 2. Tool errors should be in result:
174
+ ```typescript
175
+ {
176
+ isError: true,
177
+ content: [{
178
+ type: "text",
179
+ text: "Error description"
180
+ }]
181
+ }
182
+ ```
183
+
184
+ ### Security Considerations
185
+ 1. Input Validation:
186
+ - Validate all parameters against schemas
187
+ - Sanitize file paths and system commands
188
+ - Validate URLs and external identifiers
189
+ - Check parameter sizes and ranges
190
+
191
+ 2. Access Control:
192
+ - Implement authentication where needed
193
+ - Use appropriate authorization checks
194
+ - Audit tool usage
195
+ - Rate limit requests
196
+
197
+ 3. Resource Protection:
198
+ - Validate resource paths
199
+ - Monitor resource usage
200
+ - Implement access controls
201
+ - Rate limit requests
202
+
203
+ ### Message Handling
204
+ 1. Request Processing:
205
+ - Validate inputs thoroughly
206
+ - Use type-safe schemas
207
+ - Handle errors gracefully
208
+ - Implement timeouts
209
+
210
+ 2. Progress Reporting:
211
+ - Use progress tokens for long operations
212
+ - Report progress incrementally
213
+ - Include total progress when known
214
+
215
+ ## 5. Client Integration Guidelines
216
+
217
+ ### Client Configuration
218
+ ```json
219
+ {
220
+ "mcpServers": {
221
+ "server-name": {
222
+ "command": "command-to-run",
223
+ "args": ["arg1", "arg2"],
224
+ "env": {
225
+ "ENV_VAR": "value"
226
+ }
227
+ }
228
+ }
229
+ }
230
+ ```
231
+
232
+ ### Environment Variables
233
+ - Server inherits limited environment variables
234
+ - Custom variables must be specified in config
235
+ - Sensitive data should be in environment variables
236
+
237
+ ## 6. Testing and Debugging
238
+
239
+ ### MCP Inspector Usage
240
+ 1. Start inspector with server:
241
+ ```bash
242
+ npx mcp-inspector your-server-command
243
+ ```
244
+
245
+ 2. Features to test:
246
+ - Resource listing and reading
247
+ - Tool execution
248
+ - Prompt generation
249
+ - Error handling
250
+ - Progress reporting
251
+
252
+ ### Common Issues
253
+ 1. Connection Problems:
254
+ - Check transport configuration
255
+ - Verify server process is running
256
+ - Check for initialization errors
257
+
258
+ 2. Message Handling:
259
+ - Validate message formats
260
+ - Check handler implementations
261
+ - Verify error responses
262
+
263
+ 3. Resource Issues:
264
+ - Check file permissions
265
+ - Validate URI formats
266
+ - Verify content types
267
+
268
+ ## 7. Performance and Scaling
269
+
270
+ ### Best Practices
271
+ 1. Resource Management:
272
+ - Cache when appropriate
273
+ - Implement cleanup
274
+ - Monitor memory usage
275
+
276
+ 2. Request Handling:
277
+ - Use appropriate timeouts
278
+ - Implement rate limiting
279
+ - Handle concurrent requests
280
+
281
+ 3. Error Recovery:
282
+ - Implement reconnection logic
283
+ - Handle partial failures
284
+ - Clean up resources
285
+
286
+ ## 8. Documentation Requirements
287
+
288
+ ### Server Documentation
289
+ 1. Capabilities Documentation:
290
+ - List supported features
291
+ - Document configuration options
292
+ - Describe environment variables
293
+
294
+ 2. API Documentation:
295
+ - Document all resources
296
+ - Document all tools
297
+ - Document all prompts
298
+ - Include example usage
299
+
300
+ 3. Error Documentation:
301
+ - List possible error codes
302
+ - Describe error conditions
303
+ - Include recovery steps
304
+
305
+ ### Integration Guide
306
+ 1. Setup Instructions:
307
+ - Installation steps
308
+ - Configuration options
309
+ - Environment setup
310
+
311
+ 2. Usage Examples:
312
+ - Basic usage patterns
313
+ - Common integrations
314
+ - Error handling examples
315
+
316
+ ## 9. Versioning and Updates
317
+
318
+ ### Version Management
319
+ 1. Protocol Versioning:
320
+ - Support LATEST_PROTOCOL_VERSION
321
+ - Handle version negotiation
322
+ - Maintain compatibility
323
+
324
+ 2. Server Versioning:
325
+ - Use semantic versioning
326
+ - Document breaking changes
327
+ - Provide migration guides
328
+
329
+ ### Update Handling
330
+ 1. Capability Updates:
331
+ - Notify clients of changes
332
+ - Handle capability negotiation
333
+ - Maintain backwards compatibility
334
+
335
+ 2. Resource Updates:
336
+ - Handle resource changes
337
+ - Notify subscribed clients
338
+ - Maintain consistency
339
+
340
+ ## 10. Specific Server Types
341
+
342
+ ### Database Servers (like Airtable)
343
+ 1. Required Capabilities:
344
+ - Resources for data access
345
+ - Tools for data manipulation
346
+ - Prompts for common operations
347
+
348
+ 2. Implementation Focus:
349
+ - Connection management
350
+ - Query handling
351
+ - Data transformation
352
+ - Error handling
353
+ - Rate limiting
354
+
355
+ 3. Security Considerations:
356
+ - API key management
357
+ - Access control
358
+ - Data validation
359
+ - Request sanitization
360
+
361
+ 4. Tools to Implement:
362
+ - List databases/bases
363
+ - Create/modify tables
364
+ - Query data
365
+ - Update records
366
+ - Delete records
367
+
368
+ 5. Resource Structure:
369
+ - Database schema
370
+ - Table contents
371
+ - Query results
372
+
373
+ 6. Error Handling:
374
+ - Connection errors
375
+ - Query errors
376
+ - Rate limit errors
377
+ - Authorization errors
378
+
379
+ This guide should be used as a reference when assisting with MCP server development. Always consider the specific requirements and constraints of the project while following these guidelines.
@@ -0,0 +1,88 @@
1
+ import typescriptEslint from "@typescript-eslint/eslint-plugin";
2
+ import prettier from "eslint-plugin-prettier";
3
+ import tsParser from "@typescript-eslint/parser";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import js from "@eslint/js";
7
+ import { FlatCompat } from "@eslint/eslintrc";
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+ const compat = new FlatCompat({
12
+ baseDirectory: __dirname,
13
+ recommendedConfig: js.configs.recommended,
14
+ allConfig: js.configs.all,
15
+ });
16
+
17
+ export default [
18
+ ...compat.extends(
19
+ "eslint:recommended",
20
+ "prettier",
21
+ "plugin:@typescript-eslint/eslint-recommended",
22
+ "plugin:@typescript-eslint/recommended",
23
+ ),
24
+ {
25
+ files: ["./src/*.{ts,tsx}", "./test/*.{ts,tsx}"],
26
+ plugins: {
27
+ "@typescript-eslint": typescriptEslint,
28
+ prettier,
29
+ },
30
+
31
+ languageOptions: {
32
+ globals: {},
33
+ parser: tsParser,
34
+ ecmaVersion: 5,
35
+ sourceType: "script",
36
+
37
+ parserOptions: {
38
+ project: "./tsconfig.json",
39
+ },
40
+ },
41
+
42
+ rules: {
43
+ "prettier/prettier": "warn",
44
+
45
+ "spaced-comment": [
46
+ "error",
47
+ "always",
48
+ {
49
+ markers: ["/"],
50
+ },
51
+ ],
52
+
53
+ "no-fallthrough": "error",
54
+ "@typescript-eslint/ban-ts-comment": "warn",
55
+
56
+ "@typescript-eslint/consistent-type-imports": [
57
+ "error",
58
+ {
59
+ prefer: "type-imports",
60
+ },
61
+ ],
62
+
63
+ "@typescript-eslint/no-inferrable-types": [
64
+ "error",
65
+ {
66
+ ignoreParameters: false,
67
+ ignoreProperties: false,
68
+ },
69
+ ],
70
+
71
+ "@typescript-eslint/no-non-null-assertion": "off",
72
+ "@typescript-eslint/no-floating-promises": "error",
73
+
74
+ "@typescript-eslint/no-unused-vars": [
75
+ "warn",
76
+ {
77
+ args: "after-used",
78
+ argsIgnorePattern: "^_",
79
+ varsIgnorePattern: "^_",
80
+ ignoreRestSiblings: true,
81
+ },
82
+ ],
83
+
84
+ "@typescript-eslint/no-empty-function": ["error"],
85
+ "@typescript-eslint/restrict-template-expressions": "off",
86
+ },
87
+ },
88
+ ];
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/lib/index.mjs ADDED
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import * as os from "os";
6
+ import * as fs from "fs";
7
+ import * as path from "path";
8
+ import { spawnPromise } from "spawn-rx";
9
+ import { rimraf } from "rimraf";
10
+ import { cleanSubtitles } from "./vtt2txt.mjs";
11
+ // Get downloads directory from env or default to project root
12
+ const DOWNLOADS_DIR = process.env.DOWNLOADS_DIR || path.join(process.cwd(), "downloads");
13
+ console.error('Using downloads directory:', DOWNLOADS_DIR);
14
+ const server = new Server({
15
+ name: "mcp-video",
16
+ version: "0.5.1",
17
+ }, {
18
+ capabilities: {
19
+ tools: {},
20
+ },
21
+ });
22
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
23
+ return {
24
+ tools: [
25
+ {
26
+ name: "get_video_transcript",
27
+ description: "Download and process video subtitles for analysis from various platforms (YouTube, Vimeo, Twitter/X, TikTok, etc.) using yt-dlp. Use this tool when asked to summarize, analyze, or extract information from any video that has subtitles/closed captions. This enables Claude to understand video content through subtitles.",
28
+ inputSchema: {
29
+ type: "object",
30
+ properties: {
31
+ url: { type: "string", description: "URL of the video from any supported platform (YouTube, Vimeo, Twitter/X, TikTok, etc.)" },
32
+ },
33
+ required: ["url"],
34
+ },
35
+ },
36
+ {
37
+ name: "download_video",
38
+ description: "Download video in best quality (limited to 1080p) from various platforms (YouTube, Vimeo, Twitter/X, TikTok, etc.) using yt-dlp. Downloads are stored in the downloads directory. IMPORTANT: Clients should always provide a sanitized filename using the platform and video ID format to ensure consistent naming and avoid conflicts.",
39
+ inputSchema: {
40
+ type: "object",
41
+ properties: {
42
+ url: { type: "string", description: "URL of the video from any supported platform (YouTube, Vimeo, Twitter/X, TikTok, etc.)" },
43
+ filename: {
44
+ type: "string",
45
+ description: "Sanitized filename using platform-id format. Examples:\n- YouTube: youtube-{video_id} (e.g. 'youtube-MhOTvvmlqLM' from youtube.com/watch?v=MhOTvvmlqLM)\n- Twitter/X: x-{tweet_id} (e.g. 'x-1876565449615217019' from x.com/user/status/1876565449615217019)\n- Vimeo: vimeo-{video_id} (e.g. 'vimeo-123456789' from vimeo.com/123456789)"
46
+ },
47
+ },
48
+ required: ["url"],
49
+ },
50
+ },
51
+ ],
52
+ };
53
+ });
54
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
55
+ if (request.params.name === "get_video_transcript") {
56
+ try {
57
+ const { url } = request.params.arguments;
58
+ const tempDir = fs.mkdtempSync(`${os.tmpdir()}${path.sep}youtube-`);
59
+ await spawnPromise("yt-dlp", [
60
+ "--write-sub",
61
+ "--write-auto-sub",
62
+ "--sub-lang",
63
+ "en",
64
+ "--skip-download",
65
+ "--sub-format",
66
+ "srt",
67
+ url,
68
+ ], { cwd: tempDir, detached: true });
69
+ let content = "";
70
+ try {
71
+ fs.readdirSync(tempDir).forEach((file) => {
72
+ const fileContent = fs.readFileSync(path.join(tempDir, file), "utf8");
73
+ const cleanedContent = cleanSubtitles(fileContent);
74
+ content += `${cleanedContent}\n\n`;
75
+ });
76
+ }
77
+ finally {
78
+ rimraf.sync(tempDir);
79
+ }
80
+ return {
81
+ content: [
82
+ {
83
+ type: "text",
84
+ text: content,
85
+ },
86
+ ],
87
+ };
88
+ }
89
+ catch (err) {
90
+ return {
91
+ content: [
92
+ {
93
+ type: "text",
94
+ text: `Error downloading video: ${err}`,
95
+ },
96
+ ],
97
+ isError: true,
98
+ };
99
+ }
100
+ }
101
+ else if (request.params.name === "download_video") {
102
+ try {
103
+ const { url, filename } = request.params.arguments;
104
+ // Create downloads directory if it doesn't exist
105
+ try {
106
+ if (!fs.existsSync(DOWNLOADS_DIR)) {
107
+ fs.mkdirSync(DOWNLOADS_DIR, { recursive: true });
108
+ }
109
+ console.error('Downloads directory created/verified at:', DOWNLOADS_DIR);
110
+ }
111
+ catch (err) {
112
+ console.error('Error creating downloads directory:', err);
113
+ throw err;
114
+ }
115
+ // Get video info first
116
+ const infoResult = await spawnPromise("yt-dlp", [
117
+ "--print",
118
+ "%(title)s",
119
+ "--print",
120
+ "%(duration)s",
121
+ "--print",
122
+ "%(resolution)s",
123
+ url,
124
+ ]);
125
+ const [title, duration, resolution] = infoResult.split("\n");
126
+ // Prepare output template with absolute path
127
+ const outputTemplate = filename ?
128
+ path.join(DOWNLOADS_DIR, `${filename}.mp4`) :
129
+ path.join(DOWNLOADS_DIR, "%(title)s.%(ext)s");
130
+ // Download the video
131
+ await spawnPromise("yt-dlp", [
132
+ "-f",
133
+ "((bv*[height<=1080])/bv*)+ba/b",
134
+ "--merge-output-format",
135
+ "mp4",
136
+ "-o",
137
+ outputTemplate,
138
+ url,
139
+ ]);
140
+ // Get the final file size
141
+ const finalPath = filename ?
142
+ path.join(DOWNLOADS_DIR, `${filename}.mp4`) :
143
+ path.join(DOWNLOADS_DIR, `${title}.mp4`);
144
+ const stats = fs.statSync(finalPath);
145
+ const fileSizeMB = (stats.size / (1024 * 1024)).toFixed(2);
146
+ return {
147
+ content: [
148
+ {
149
+ type: "text",
150
+ text: `Successfully downloaded video:
151
+ Title: ${title}
152
+ Duration: ${duration} seconds
153
+ Resolution: ${resolution}
154
+ File size: ${fileSizeMB} MB
155
+ Saved to: ${finalPath}`,
156
+ },
157
+ ],
158
+ };
159
+ }
160
+ catch (err) {
161
+ return {
162
+ content: [
163
+ {
164
+ type: "text",
165
+ text: `Error downloading video: ${err}`,
166
+ },
167
+ ],
168
+ isError: true,
169
+ };
170
+ }
171
+ }
172
+ else {
173
+ throw new Error(`Unknown tool: ${request.params.name}`);
174
+ }
175
+ });
176
+ async function runServer() {
177
+ const transport = new StdioServerTransport();
178
+ await server.connect(transport);
179
+ }
180
+ runServer().catch(console.error);
181
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function cleanSubtitles(vttContent: string): string;
@@ -0,0 +1,22 @@
1
+ export function cleanSubtitles(vttContent) {
2
+ // Split into lines
3
+ const lines = vttContent.split('\n');
4
+ const cleanedText = new Set(); // Use Set to remove duplicates
5
+ for (let line of lines) {
6
+ // Skip WebVTT header, timestamps, and empty lines
7
+ if (line.trim() === 'WEBVTT' || line.trim() === '' || /^\d{2}:\d{2}/.test(line)) {
8
+ continue;
9
+ }
10
+ // Remove HTML-style tags and clean the text
11
+ line = line.replace(/<[^>]*>/g, '')
12
+ .replace(/\[.*?\]/g, '') // Remove square brackets and their contents
13
+ .trim();
14
+ // If we have actual text, add it
15
+ if (line) {
16
+ cleanedText.add(line);
17
+ }
18
+ }
19
+ // Convert Set back to array and join with newlines
20
+ return Array.from(cleanedText).join('\n');
21
+ }
22
+ //# sourceMappingURL=vtt2txt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vtt2txt.mjs","sourceRoot":"","sources":["../src/vtt2txt.mts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC7C,mBAAmB;IACnB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC,CAAC,+BAA+B;IAEtE,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC;QACrB,kDAAkD;QAClD,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9E,SAAS;QACb,CAAC;QAED,4CAA4C;QAC5C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;aACxB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,4CAA4C;aACpE,IAAI,EAAE,CAAC;QAElB,iCAAiC;QACjC,IAAI,IAAI,EAAE,CAAC;YACP,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,mDAAmD;IACnD,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,CAAC"}