get_trending_topics
Retrieve trending topics from social media platforms like Twitter, Mastodon, and LinkedIn to identify popular conversations and content opportunities.
Instructions
Get trending topics from social media platforms
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| platform | Yes | Social media platform to get trending topics from | |
| category | No | Category of trending topics (e.g., "technology", "entertainment") | |
| count | No | Number of trending topics to return |
Implementation Reference
- src/index.ts:545-616 (handler)Main handler function for the get_trending_topics MCP tool. Aggregates trending topics from multiple platforms (Twitter, Mastodon, LinkedIn) based on parameters and returns formatted JSON response.
private async handleGetTrendingTopics(args: any) { logger.info('Getting trending topics', { platform: args.platform }); try { const platform = args.platform || 'all'; const category = args.category || 'all'; const count = args.count || 10; const results: Record<string, any> = {}; // Get Twitter trending topics if (platform === 'all' || platform === 'twitter') { try { results.twitter = await twitterClient.getTrendingTopics(category, count); } catch (error) { logger.error('Error getting Twitter trending topics', { error: error instanceof Error ? error.message : String(error) }); results.twitter = []; } } // Get Mastodon trending tags if (platform === 'all' || platform === 'mastodon') { try { results.mastodon = await mastodonClient.getTrendingTags(count); } catch (error) { logger.error('Error getting Mastodon trending tags', { error: error instanceof Error ? error.message : String(error) }); results.mastodon = []; } } // Get LinkedIn trending topics if (platform === 'all' || platform === 'linkedin') { try { results.linkedin = await linkedinClient.getTrendingTopics(count); } catch (error) { logger.error('Error getting LinkedIn trending topics', { error: error instanceof Error ? error.message : String(error) }); results.linkedin = []; } } return { content: [ { type: 'text', text: JSON.stringify({ platform, category, count, trendingTopics: platform === 'all' ? results : results[platform], status: 'success', }, null, 2), }, ], }; } catch (error) { logger.error('Error getting trending topics', { platform: args.platform, error: error instanceof Error ? error.message : String(error) }); throw error; } } - src/index.ts:122-144 (registration)Registration of the get_trending_topics tool with the MCP server, including name, description, and input schema definition.
{ name: 'get_trending_topics', description: 'Get trending topics from social media platforms', inputSchema: { type: 'object', properties: { platform: { type: 'string', enum: ['twitter', 'mastodon', 'linkedin', 'all'], description: 'Social media platform to get trending topics from', }, category: { type: 'string', description: 'Category of trending topics (e.g., "technology", "entertainment")', }, count: { type: 'number', description: 'Number of trending topics to return', }, }, required: ['platform'], }, }, - Twitter client method that fetches trending topics using Twitter API v1 trendsByPlace endpoint (global WOEID=1), with rate limiting, error handling, category filtering placeholder, and mock fallback data.
async getTrendingTopics(category?: string, count: number = 10): Promise<any> { logger.info('Getting trending topics', { category, count }); try { // Use rate limit manager to handle API rate limits const result = await rateLimitManager.executeRequest({ api: 'twitter', endpoint: 'trends', method: 'GET', priority: 'medium', retryCount: 0, maxRetries: config.rateLimit.maxRetries, execute: async () => { // Get WOEID for global trends (1 is global) const woeid = 1; if (config.twitter.debug) { logger.info('Twitter API Debug: Getting trends', { woeid, category, count }); } try { // Try to get trends using the bearer client (app-only context) // This requires the "trends:read" scope const trends = await this.bearerClient.v1.trendsByPlace(woeid); if (config.twitter.debug) { logger.info('Twitter API Debug: Trends response', { trendCount: trends[0]?.trends?.length || 0, asOf: trends[0]?.as_of, location: trends[0]?.locations?.[0]?.name }); } return trends; } catch (error) { logger.error('Error getting trends with bearer token', { error: error instanceof Error ? error.message : String(error) }); // Try to get trends using the user context try { const trends = await this.client.v1.trendsByPlace(woeid); if (config.twitter.debug) { logger.info('Twitter API Debug: Trends response (user context)', { trendCount: trends[0]?.trends?.length || 0, asOf: trends[0]?.as_of, location: trends[0]?.locations?.[0]?.name }); } return trends; } catch (userError) { logger.error('Error getting trends with user context', { error: userError instanceof Error ? userError.message : String(userError) }); // Fall back to mock implementation if both methods fail logger.info('Falling back to mock implementation for trends'); const mockTrends = { 0: { trends: [ { name: '#AI', url: 'https://twitter.com/search?q=%23AI', promoted_content: null, query: '%23AI', tweet_volume: 12345 }, { name: '#MachineLearning', url: 'https://twitter.com/search?q=%23MachineLearning', promoted_content: null, query: '%23MachineLearning', tweet_volume: 10234 }, { name: '#DataScience', url: 'https://twitter.com/search?q=%23DataScience', promoted_content: null, query: '%23DataScience', tweet_volume: 9876 }, { name: '#Python', url: 'https://twitter.com/search?q=%23Python', promoted_content: null, query: '%23Python', tweet_volume: 8765 }, { name: '#JavaScript', url: 'https://twitter.com/search?q=%23JavaScript', promoted_content: null, query: '%23JavaScript', tweet_volume: 7654 }, { name: '#Cybersecurity', url: 'https://twitter.com/search?q=%23Cybersecurity', promoted_content: null, query: '%23Cybersecurity', tweet_volume: 6543 }, { name: '#Cloud', url: 'https://twitter.com/search?q=%23Cloud', promoted_content: null, query: '%23Cloud', tweet_volume: 5432 }, { name: '#DevOps', url: 'https://twitter.com/search?q=%23DevOps', promoted_content: null, query: '%23DevOps', tweet_volume: 4321 }, { name: '#IoT', url: 'https://twitter.com/search?q=%23IoT', promoted_content: null, query: '%23IoT', tweet_volume: 3210 }, { name: '#BigData', url: 'https://twitter.com/search?q=%23BigData', promoted_content: null, query: '%23BigData', tweet_volume: 2109 }, { name: '#Blockchain', url: 'https://twitter.com/search?q=%23Blockchain', promoted_content: null, query: '%23Blockchain', tweet_volume: 1987 }, { name: '#5G', url: 'https://twitter.com/search?q=%235G', promoted_content: null, query: '%235G', tweet_volume: 1876 }, ], as_of: new Date().toISOString(), created_at: new Date().toISOString(), locations: [{ name: 'Worldwide', woeid: 1 }] } }; if (config.twitter.debug) { logger.info('Twitter API Debug: Mock trends response', { trendCount: mockTrends[0].trends.length, asOf: mockTrends[0].as_of, location: mockTrends[0].locations[0].name }); } return mockTrends; } } } }); // Filter trends by category if specified let filteredTrends = result[0].trends; if (category && category !== 'all') { // Note: Twitter API doesn't provide category information for trends // This is a placeholder for category filtering logger.info('Category filtering not available for Twitter trends'); } // Limit the number of trends filteredTrends = filteredTrends.slice(0, count); // Define the trend type interface TwitterTrend { name: string; url: string; promoted_content: string | null; query: string; tweet_volume: number | null; } // Format the trends const formattedTrends = filteredTrends.map((trend: TwitterTrend) => ({ name: trend.name, volume: trend.tweet_volume || 0, category: category || 'all', })); logger.info('Trending topics retrieved successfully', { count: formattedTrends.length }); return formattedTrends; } catch (error) { logger.error('Error getting trending topics', { error: error instanceof Error ? error.message : String(error) }); throw error; } } - LinkedIn client placeholder method for getTrendingTopics (no direct API available), returns mock popular topics/hashtags with rate limiting.
async getTrendingTopics(count: number = 10): Promise<any> { logger.info('Getting trending topics', { count }); try { // Use rate limit manager to handle API rate limits const result = await rateLimitManager.executeRequest({ api: 'linkedin', endpoint: 'trendingTopics', method: 'GET', priority: 'medium', retryCount: 0, maxRetries: config.rateLimit.maxRetries, execute: async () => { // LinkedIn doesn't have a direct trending topics API // This is a placeholder that would normally call the LinkedIn API // to get popular content in the user's network // For now, return some placeholder trending topics return [ { name: 'AI', volume: 1000 }, { name: 'MachineLearning', volume: 850 }, { name: 'DataScience', volume: 750 }, { name: 'Leadership', volume: 700 }, { name: 'Innovation', volume: 650 }, { name: 'DigitalTransformation', volume: 600 }, { name: 'FutureOfWork', volume: 550 }, { name: 'RemoteWork', volume: 500 }, { name: 'Entrepreneurship', volume: 450 }, { name: 'Sustainability', volume: 400 }, { name: 'CareerAdvice', volume: 350 }, { name: 'ProductManagement', volume: 300 }, ]; } }); // Limit the number of trends const limitedTrends = result.slice(0, count); // Format the trends const formattedTrends = limitedTrends.map((trend: any) => ({ name: `#${trend.name}`, volume: trend.volume, category: 'all', // LinkedIn doesn't provide category information })); logger.info('Trending topics retrieved successfully', { count: formattedTrends.length }); return formattedTrends; } catch (error) { logger.error('Error getting trending topics', { error: error instanceof Error ? error.message : String(error) }); throw error; } }