YouTube Integration

  • src
#!/usr/bin/env node import { Server } from '@highlight-ai/mcp-sdk/server/index.js' import { StdioServerTransport } from '@highlight-ai/mcp-sdk/server/stdio.js' import { ListToolsRequestSchema, GetAuthTokenRequestSchema, CallToolRequestSchema, ErrorCode, McpError, } from '@highlight-ai/mcp-sdk/types.js' import { z } from 'zod' import { YoutubeTranscript } from 'youtube-transcript' /** * Helper function to extract video ID from YouTube URL */ export function getVideoId(url: string): string { const regex = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/ const match = url.match(regex) if (!match) throw new Error('Invalid YouTube URL') return match[1] } /** * Get transcript from a YouTube video URL */ export async function getTranscript(url: string): Promise<string> { if (!url) { throw new Error('URL is required') } try { const videoId = getVideoId(url) const transcript = await YoutubeTranscript.fetchTranscript(videoId) return transcript.map((item) => item.text).join(' ') } catch (error) { throw new Error(`Failed to get transcript: ${error instanceof Error ? error.message : 'Unknown error'}`) } } class YoutubeTranscriptServer { private server: Server constructor() { this.server = new Server( { name: 'youtube-transcript-server', version: '0.0.1', }, { capabilities: { resources: {}, tools: {}, }, }, ) this.setupHandlers() this.setupErrorHandling() } private setupErrorHandling(): void { this.server.onerror = (error) => { console.error('[MCP Error]', error) } process.on('SIGINT', async () => { await this.server.close() process.exit(0) }) } private setupHandlers(): void { this.setupToolHandlers() } private setupToolHandlers(): void { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'get_youtube_transcript', description: 'Extracts and returns the complete text transcript from a YouTube video URL. This tool processes the video\'s closed captions or subtitles and combines them into a single continuous text. The transcript includes all spoken content and on-screen text from the video.', inputSchema: { type: 'object', properties: { videoUrl: { type: 'string', description: 'The full URL of the YouTube video (supports both youtube.com and youtu.be formats). Example: https://www.youtube.com/watch?v=<video_id>', }, }, required: ['videoUrl'], }, }, ], })) // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== 'get_youtube_transcript') { throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`) } const url = String(request.params.arguments?.videoUrl) const transcriptText = await getTranscript(url) return { content: [ { type: 'text', text: transcriptText, }, ], } }) } async run(): Promise<void> { const transport = new StdioServerTransport() await this.server.connect(transport) console.log('Youtube Transcript MCP server running on stdio') } } const server = new YoutubeTranscriptServer() server.run().catch(console.error)