generate_linkedin_post
Generate LinkedIn post drafts from YouTube video content by summarizing key points and applying specified tone and hashtags.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| summary | Yes | Summary of the video content | |
| videoTitle | Yes | Title of the YouTube video | |
| speakerName | No | Name of the speaker in the video (optional) | |
| hashtags | No | Relevant hashtags (optional) | |
| tone | No | Tone of the LinkedIn post | first-person |
| includeCallToAction | No | Whether to include a call to action |
Implementation Reference
- src/modules/post-generator.js:14-99 (handler)Core handler function that generates a LinkedIn post using OpenAI GPT based on video summary, title, speaker, hashtags, tone, etc.export async function generateLinkedInPost( summary, videoTitle, speakerName = null, hashtags = [], tone = "first-person", includeCallToAction = true, apiKey ) { if (!apiKey) { throw new Error("OpenAI API key not provided"); } if (!summary || summary.trim().length === 0) { throw new Error("Empty summary provided"); } console.log(`Generating LinkedIn post with tone: ${tone}`); try { // Initialize OpenAI client with provided API key const openai = new OpenAI({ apiKey: apiKey, }); // Prepare hashtag string const hashtagString = hashtags && hashtags.length > 0 ? hashtags.map(tag => tag.startsWith('#') ? tag : `#${tag}`).join(' ') : ''; // Prepare speaker reference const speakerReference = speakerName ? `by ${speakerName}` : ''; const response = await openai.chat.completions.create({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: `You are a professional LinkedIn content creator. Create a compelling LinkedIn post in a ${tone} tone based on the provided video summary. The post should be between 500-1200 characters (not including hashtags). Structure the post with: 1. An attention-grabbing hook 2. 2-3 key insights from the video 3. A personal reflection or takeaway ${includeCallToAction ? '4. A soft call to action (e.g., asking a question, inviting comments)' : ''} The post should feel authentic, professional, and valuable to LinkedIn readers. Avoid clickbait or overly promotional language.` }, { role: "user", content: `Create a LinkedIn post based on this YouTube video: Title: ${videoTitle} ${speakerReference} Summary: ${summary} ${hashtagString ? `Suggested hashtags: ${hashtagString}` : ''} Please format the post ready to copy and paste to LinkedIn.` } ], temperature: 0.7, max_tokens: 700 }); if (response.choices && response.choices.length > 0) { let post = response.choices[0].message.content.trim(); // Ensure hashtags are at the end if they weren't included if (hashtagString && !post.includes(hashtagString)) { post += `\n\n${hashtagString}`; } return post; } else { throw new Error("No post generated"); } } catch (error) { console.error("Post generation error:", error); throw new Error(`Failed to generate LinkedIn post: ${error.message}`); } }
- src/server.js:167-220 (registration)MCP tool registration for 'generate_linkedin_post' including Zod input schema, wrapper handler that checks API key and calls the core generateLinkedInPost function, and description.server.tool( "generate_linkedin_post", { summary: z.string().describe("Summary of the video content"), videoTitle: z.string().describe("Title of the YouTube video"), speakerName: z.string().optional().describe("Name of the speaker in the video (optional)"), hashtags: z.array(z.string()).optional().describe("Relevant hashtags (optional)"), tone: z.enum(["first-person", "third-person", "thought-leader"]) .default("first-person") .describe("Tone of the LinkedIn post"), includeCallToAction: z.boolean().default(true) .describe("Whether to include a call to action") }, async ({ summary, videoTitle, speakerName, hashtags, tone, includeCallToAction }) => { try { // Check if OpenAI API key is set if (!apiKeyManager.hasOpenAIKey()) { throw new Error("OpenAI API key not set. Please use the set_api_keys tool first."); } const post = await generateLinkedInPost( summary, videoTitle, speakerName, hashtags, tone, includeCallToAction, apiKeyManager.getOpenAIKey() ); return { content: [{ type: "text", text: JSON.stringify({ success: true, post }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ success: false, error: error.message }, null, 2) }], isError: true }; } }, { description: "Generate a LinkedIn post draft from a video summary" } );
- src/server.js:169-179 (schema)Zod schema defining input parameters for the generate_linkedin_post tool.{ summary: z.string().describe("Summary of the video content"), videoTitle: z.string().describe("Title of the YouTube video"), speakerName: z.string().optional().describe("Name of the speaker in the video (optional)"), hashtags: z.array(z.string()).optional().describe("Relevant hashtags (optional)"), tone: z.enum(["first-person", "third-person", "thought-leader"]) .default("first-person") .describe("Tone of the LinkedIn post"), includeCallToAction: z.boolean().default(true) .describe("Whether to include a call to action") },