create_post
Create and publish social media content across platforms using natural language instructions, with options for previewing, platform selection, and conversation integration.
Instructions
Create and post content to social media platforms based on natural language instructions
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| instruction | Yes | Natural language instruction for the post (e.g., "Post about the latest AI developments") | |
| platforms | No | Social media platforms to post to | |
| postImmediately | No | Whether to post immediately or return a preview | |
| conversationId | No | ID of an existing conversation to continue | |
| questionId | No | ID of the question being answered | |
| answer | No | Answer to the question | |
| ignoreHistory | No | Whether to ignore similar posts in history | |
| actionableInsights | No | Whether to include actionable insights in the post |
Implementation Reference
- src/index.ts:216-483 (handler)Core handler function implementing the 'create_post' tool. Orchestrates NLP intent parsing, conversation and question management, history checks, topic research via aggregator, multi-platform content generation, and optional immediate posting using platform-specific clients.private async handleCreatePost(args: any) { logger.info('Creating post', { instruction: args.instruction }); try { // Get conversation ID if provided const conversationId = args.conversationId; // Parse the instruction to extract intent const intent = await nlpProcessor.parseIntent(args.instruction, conversationId); // Override platforms if specified in args if (args.platforms) { if (args.platforms === 'all') { intent.platforms = [SocialPlatform.TWITTER, SocialPlatform.MASTODON, SocialPlatform.LINKEDIN]; } else if (Array.isArray(args.platforms)) { intent.platforms = []; if (args.platforms.includes('twitter')) { intent.platforms.push(SocialPlatform.TWITTER); } if (args.platforms.includes('mastodon')) { intent.platforms.push(SocialPlatform.MASTODON); } if (args.platforms.includes('linkedin')) { intent.platforms.push(SocialPlatform.LINKEDIN); } } } // Override scheduling requirements if postImmediately is specified if (args.postImmediately !== undefined) { if (!intent.schedulingRequirements) { intent.schedulingRequirements = {}; } intent.schedulingRequirements.postImmediately = args.postImmediately; } // Set actionable insights if specified if (args.actionableInsights !== undefined) { intent.actionableInsights = args.actionableInsights ? 'Include practical steps that readers can take immediately.' : undefined; } // Check if there are similar posts in history (unless ignoreHistory is true) if (!args.ignoreHistory) { const similarPosts = historyManager.getSimilarPosts(intent.topic, 0.7); if (similarPosts.length > 0) { logger.info('Found similar posts in history', { count: similarPosts.length, topic: intent.topic, }); // Return similar posts return { content: [ { type: 'text', text: JSON.stringify({ instruction: args.instruction, intent, similarPosts, status: 'similar_posts_found', message: 'Similar posts were found in history. Consider modifying your topic or focusing on a different aspect.', }, null, 2), }, ], }; } } else { logger.info('Ignoring history check', { topic: intent.topic }); } // Create or get conversation let conversation; if (conversationId) { conversation = conversationManager.getConversation(conversationId); if (!conversation) { logger.warn('Conversation not found, creating new conversation', { conversationId }); conversation = conversationManager.createConversation(intent); } } else { conversation = conversationManager.createConversation(intent); } // Store conversation ID in intent intent.conversationId = conversation.id; // Check if we need to ask questions if (conversation.state === ConversationState.INITIAL_REQUEST) { // Generate questions const questionIds = conversationManager.generateQuestions(conversation.id); if (questionIds.length > 0) { // Get the first question const question = conversationManager.getCurrentQuestion(conversation.id); if (question) { logger.info('Asking question', { conversationId: conversation.id, questionId: question.id, questionType: question.type, }); // Return question return { content: [ { type: 'text', text: JSON.stringify({ instruction: args.instruction, intent, conversationId: conversation.id, question: question.text, questionId: question.id, status: 'question', }, null, 2), }, ], }; } } } else if (conversation.state === ConversationState.ASKING_QUESTIONS) { // Check if we have a question to answer if (args.questionId && args.answer) { // Answer the question conversationManager.answerQuestion(conversation.id, args.questionId, args.answer); // Get the next question const nextQuestion = conversationManager.getCurrentQuestion(conversation.id); if (nextQuestion) { logger.info('Asking next question', { conversationId: conversation.id, questionId: nextQuestion.id, questionType: nextQuestion.type, }); // Return next question return { content: [ { type: 'text', text: JSON.stringify({ instruction: args.instruction, intent, conversationId: conversation.id, question: nextQuestion.text, questionId: nextQuestion.id, status: 'question', }, null, 2), }, ], }; } } else { // Get the current question const currentQuestion = conversationManager.getCurrentQuestion(conversation.id); if (currentQuestion) { logger.info('Asking current question', { conversationId: conversation.id, questionId: currentQuestion.id, questionType: currentQuestion.type, }); // Return current question return { content: [ { type: 'text', text: JSON.stringify({ instruction: args.instruction, intent, conversationId: conversation.id, question: currentQuestion.text, questionId: currentQuestion.id, status: 'question', }, null, 2), }, ], }; } } } // Update conversation state to generating content conversationManager.updateState(conversation.id, ConversationState.GENERATING_CONTENT); // Research the topic const researchOptions = { includeHashtags: intent.researchRequirements?.includeHashtags || true, includeFacts: intent.researchRequirements?.includeFacts || true, includeTrends: intent.researchRequirements?.includeTrends || true, includeNews: intent.researchRequirements?.includeNews || true, }; const research = await researchAggregator.researchTopic(intent.topic, researchOptions); // Generate content for each platform const content = await contentGenerator.generateContentForPlatforms( intent, research, intent.platforms ); // Update conversation state to preview conversationManager.updateState(conversation.id, ConversationState.PREVIEW); // Post content if postImmediately is true if (intent.schedulingRequirements?.postImmediately) { const postResults = await this.postContent(content); // Update conversation state to completed conversationManager.updateState(conversation.id, ConversationState.COMPLETED); // Add to history const keywords = research.hashtags || []; historyManager.addToHistory( intent.topic, args.instruction, intent.platforms, content, keywords ); return { content: [ { type: 'text', text: JSON.stringify({ instruction: args.instruction, intent, research, content, postResults, conversationId: conversation.id, status: 'posted', }, null, 2), }, ], }; } // Return preview if postImmediately is false return { content: [ { type: 'text', text: JSON.stringify({ instruction: args.instruction, intent, research, content, conversationId: conversation.id, status: 'preview', }, null, 2), }, ], }; } catch (error) { logger.error('Error creating post', { instruction: args.instruction, error: error instanceof Error ? error.message : String(error) }); throw error; } }
- src/index.ts:79-120 (schema)Input schema validating parameters for the create_post tool call.inputSchema: { type: 'object', properties: { instruction: { type: 'string', description: 'Natural language instruction for the post (e.g., "Post about the latest AI developments")', }, platforms: { type: 'array', items: { type: 'string', enum: ['twitter', 'mastodon', 'linkedin', 'all'], }, description: 'Social media platforms to post to', }, postImmediately: { type: 'boolean', description: 'Whether to post immediately or return a preview', }, conversationId: { type: 'string', description: 'ID of an existing conversation to continue', }, questionId: { type: 'string', description: 'ID of the question being answered', }, answer: { type: 'string', description: 'Answer to the question', }, ignoreHistory: { type: 'boolean', description: 'Whether to ignore similar posts in history', }, actionableInsights: { type: 'boolean', description: 'Whether to include actionable insights in the post', }, }, required: ['instruction'], },
- src/index.ts:76-121 (registration)Registers 'create_post' tool in the MCP ListTools response with name, description, and input schema.{ name: 'create_post', description: 'Create and post content to social media platforms based on natural language instructions', inputSchema: { type: 'object', properties: { instruction: { type: 'string', description: 'Natural language instruction for the post (e.g., "Post about the latest AI developments")', }, platforms: { type: 'array', items: { type: 'string', enum: ['twitter', 'mastodon', 'linkedin', 'all'], }, description: 'Social media platforms to post to', }, postImmediately: { type: 'boolean', description: 'Whether to post immediately or return a preview', }, conversationId: { type: 'string', description: 'ID of an existing conversation to continue', }, questionId: { type: 'string', description: 'ID of the question being answered', }, answer: { type: 'string', description: 'Answer to the question', }, ignoreHistory: { type: 'boolean', description: 'Whether to ignore similar posts in history', }, actionableInsights: { type: 'boolean', description: 'Whether to include actionable insights in the post', }, }, required: ['instruction'], }, },
- src/index.ts:182-183 (registration)Tool dispatch in CallToolRequest handler routing 'create_post' calls to the handler method.case 'create_post': return await this.handleCreatePost(request.params.arguments);
- src/index.ts:488-540 (helper)Helper method called by handler to execute actual posting to social platforms using imported platform clients.private async postContent(content: Record<SocialPlatform, Content>): Promise<any> { const results: Record<string, any> = {}; // Post to Twitter if (content[SocialPlatform.TWITTER]) { try { results.twitter = await twitterClient.postTweet(content[SocialPlatform.TWITTER]); } catch (error) { logger.error('Error posting to Twitter', { error: error instanceof Error ? error.message : String(error) }); results.twitter = { success: false, error: error instanceof Error ? error.message : String(error), }; } } // Post to Mastodon if (content[SocialPlatform.MASTODON]) { try { results.mastodon = await mastodonClient.postStatus(content[SocialPlatform.MASTODON]); } catch (error) { logger.error('Error posting to Mastodon', { error: error instanceof Error ? error.message : String(error) }); results.mastodon = { success: false, error: error instanceof Error ? error.message : String(error), }; } } // Post to LinkedIn if (content[SocialPlatform.LINKEDIN]) { try { results.linkedin = await linkedinClient.postShare(content[SocialPlatform.LINKEDIN]); } catch (error) { logger.error('Error posting to LinkedIn', { error: error instanceof Error ? error.message : String(error) }); results.linkedin = { success: false, error: error instanceof Error ? error.message : String(error), }; } } return results; }