Skip to main content
Glama

YouTube to LinkedIn MCP Server

main.py10 kB
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.utils import get_openapi import logging from dotenv import load_dotenv from app.routers import transcript, summary, post_generation, output # Load environment variables load_dotenv() # Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) logger = logging.getLogger(__name__) # Create FastAPI app app = FastAPI( title="YouTube to LinkedIn MCP Server", description="Model Context Protocol server for generating LinkedIn posts from YouTube videos", version="1.0.0", ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], # In production, replace with specific origins allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(transcript.router, prefix="/api/v1", tags=["Transcript"]) app.include_router(summary.router, prefix="/api/v1", tags=["Summary"]) app.include_router(post_generation.router, prefix="/api/v1", tags=["Post Generation"]) app.include_router(output.router, prefix="/api/v1", tags=["Output"]) # Tool listing endpoint for Smithery @app.get("/list-tools") async def list_tools(): """ List available tools for Smithery integration. This endpoint does not require authentication. """ return { "schema_version": "v1", "name_for_human": "YouTube to LinkedIn MCP Server", "name_for_model": "youtube_to_linkedin", "description_for_human": "Generate LinkedIn posts from YouTube videos", "description_for_model": "This service extracts transcripts from YouTube videos, summarizes them, and generates LinkedIn posts.", "auth": { "type": "none" }, "api": { "type": "openapi", "url": "/openapi.json" }, "tools": [ { "type": "function", "function": { "name": "extract_transcript", "description": "Extract transcript from a YouTube video", "parameters": { "type": "object", "properties": { "youtube_url": { "type": "string", "description": "URL of the YouTube video" }, "language": { "type": "string", "description": "Language code for the transcript (default: en)" }, "youtube_api_key": { "type": "string", "description": "Optional YouTube Data API key" } }, "required": ["youtube_url"] } } }, { "type": "function", "function": { "name": "generate_summary", "description": "Generate a summary from a video transcript", "parameters": { "type": "object", "properties": { "transcript": { "type": "string", "description": "Video transcript text" }, "video_title": { "type": "string", "description": "Title of the video" }, "tone": { "type": "string", "description": "Tone of the summary", "enum": ["educational", "inspirational", "professional", "conversational", "thought_leader"] }, "audience": { "type": "string", "description": "Target audience", "enum": ["general", "technical", "executive", "entry_level", "industry_specific"] }, "max_length": { "type": "integer", "description": "Maximum summary length in words" }, "min_length": { "type": "integer", "description": "Minimum summary length in words" }, "openai_api_key": { "type": "string", "description": "Optional OpenAI API key" } }, "required": ["transcript", "video_title", "tone", "audience"] } } }, { "type": "function", "function": { "name": "generate_post", "description": "Generate a LinkedIn post from a video summary", "parameters": { "type": "object", "properties": { "summary": { "type": "string", "description": "Video summary" }, "video_title": { "type": "string", "description": "Title of the video" }, "video_url": { "type": "string", "description": "URL of the YouTube video" }, "speaker_name": { "type": "string", "description": "Name of the speaker in the video (optional)" }, "hashtags": { "type": "array", "items": { "type": "string" }, "description": "List of hashtags to include (optional)" }, "tone": { "type": "string", "description": "Tone of the post", "enum": ["educational", "inspirational", "professional", "conversational", "thought_leader"] }, "voice": { "type": "string", "description": "Voice of the post", "enum": ["first_person", "third_person"] }, "audience": { "type": "string", "description": "Target audience", "enum": ["general", "technical", "executive", "entry_level", "industry_specific"] }, "include_call_to_action": { "type": "boolean", "description": "Whether to include a call to action" }, "max_length": { "type": "integer", "description": "Maximum post length in characters" }, "openai_api_key": { "type": "string", "description": "Optional OpenAI API key" } }, "required": ["summary", "video_title", "video_url", "tone", "voice", "audience"] } } }, { "type": "function", "function": { "name": "format_output", "description": "Format the LinkedIn post for output", "parameters": { "type": "object", "properties": { "post_content": { "type": "string", "description": "LinkedIn post content" }, "format": { "type": "string", "description": "Output format", "enum": ["json", "text", "markdown", "html"] } }, "required": ["post_content", "format"] } } } ] } # Root endpoint @app.get("/") async def root(): return { "message": "YouTube to LinkedIn MCP Server", "docs": "/docs", "version": "1.0.0", } # Health check endpoint @app.get("/health") async def health_check(): return {"status": "healthy"} # Custom OpenAPI schema def custom_openapi(): if app.openapi_schema: return app.openapi_schema openapi_schema = get_openapi( title=app.title, version=app.version, description=app.description, routes=app.routes, ) app.openapi_schema = openapi_schema return app.openapi_schema app.openapi = custom_openapi if __name__ == "__main__": import uvicorn uvicorn.run("app.main:app", host="0.0.0.0", port=8000, reload=True)

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/NvkAnirudh/YT-to-LinkedIn-MCP-Server'

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