Skip to main content
Glama
jedarden

YouTube Transcript DL MCP Server

by jedarden

get_transcript

Extract YouTube video transcripts in text, JSON, or SRT format by providing the video ID or URL. Supports multiple languages for accurate transcript retrieval.

Instructions

Extract transcript from a single YouTube video

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
formatNoOutput formatjson
languageNoLanguage code (e.g., "en", "es", "fr")en
videoIdYesYouTube video ID or URL

Implementation Reference

  • Core handler function that implements the get_transcript tool logic: extracts video ID, checks cache, executes Python script to fetch transcript data, formats response, handles errors, and caches results.
    public async getTranscript( videoId: string, language: string = 'en', format: 'text' | 'json' | 'srt' = 'json' ): Promise<TranscriptResponse> { try { // Clean video ID from URL if needed const cleanVideoId = this.extractVideoId(videoId); const cacheKey = `transcript:${cleanVideoId}:${language}:${format}`; // Check cache first const cached = this.cache.get<TranscriptResponse>(cacheKey); if (cached) { this.logger.debug(`Cache hit for video ${cleanVideoId}`); return cached; } this.logger.info(`Fetching transcript for video: ${cleanVideoId}`); // Call Python script to get transcript const command = `python3 "${this.pythonScript}" fetch --video-id "${cleanVideoId}" --language "${language}"`; const { stdout, stderr } = await execAsync(command); if (stderr) { this.logger.warn(`Python script warning: ${stderr}`); } const pythonResult: PythonTranscriptResult = JSON.parse(stdout); if (!pythonResult.success) { throw new Error(pythonResult.error || 'Failed to fetch transcript'); } // Convert to our format const transcript: TranscriptItem[] = pythonResult.transcript.map(item => ({ text: item.text, start: item.start, duration: item.duration })); const response: TranscriptResponse = { videoId: cleanVideoId, title: await this.getVideoTitle(cleanVideoId), // Try to get title language, transcript, metadata: { extractedAt: new Date().toISOString(), source: 'youtube-transcript-api', duration: pythonResult.metadata?.duration || transcript.reduce((acc, item) => acc + item.duration, 0) } }; // Cache the response this.cache.set(cacheKey, response); this.logger.info(`Successfully extracted transcript for video ${cleanVideoId}`); return response; } catch (error) { this.logger.error(`Failed to extract transcript for video ${videoId}:`, error); // Return structured error response return { videoId: this.extractVideoId(videoId), title: 'Error', language, transcript: [], metadata: { extractedAt: new Date().toISOString(), source: 'youtube-transcript-api', error: error instanceof Error ? error.message : 'Unknown error' } }; } }
  • MCP server handler for 'get_transcript' tool calls: validates parameters and delegates to YouTubeTranscriptService.
    private async handleGetTranscript(args: any) { const { videoId, language = 'en', format = 'json' } = args; if (!videoId) { throw new McpError(ErrorCode.InvalidParams, 'videoId is required'); } const result = await this.transcriptService.getTranscript(videoId, language, format); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }
  • Input schema and metadata definition for the get_transcript tool, used in tools/list response.
    name: 'get_transcript', description: 'Extract transcript from a single YouTube video', inputSchema: { type: 'object', properties: { videoId: { type: 'string', description: 'YouTube video ID or URL' }, language: { type: 'string', description: 'Language code (e.g., "en", "es", "fr")', default: 'en' }, format: { type: 'string', enum: ['text', 'json', 'srt'], description: 'Output format', default: 'json' } }, required: ['videoId'] } },
  • Registration of tool call handler via MCP SDK's setRequestHandler for CallToolRequestSchema, with switch dispatching to get_transcript handler.
    // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'get_transcript': return await this.handleGetTranscript(args); case 'get_bulk_transcripts': return await this.handleGetBulkTranscripts(args); case 'get_playlist_transcripts': return await this.handleGetPlaylistTranscripts(args); case 'format_transcript': return await this.handleFormatTranscript(args); case 'get_cache_stats': return await this.handleGetCacheStats(); case 'clear_cache': return await this.handleClearCache(); case 'list_transcripts': return await this.handleListTranscripts(args); default: throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${name}` ); } } catch (error) { this.logger.error(`Error handling tool call ${name}:`, error); throw new McpError( ErrorCode.InternalError, `Error executing tool: ${error instanceof Error ? error.message : 'Unknown error'}` ); } });
  • Python helper script containing the actual YouTubeTranscriptApi.get_transcript call invoked by the JS service.
    transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=[language]) return { 'success': True, 'videoId': video_id, 'language': language, 'transcript': transcript, 'metadata': { 'extractedAt': None, # Will be set by Node.js 'source': 'youtube-transcript-api', 'itemCount': len(transcript), 'duration': sum(item['duration'] for item in transcript) }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jedarden/yt-transcript-dl-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server