Skip to main content
Glama

Twitter MCP Server

user.handlers.ts6.93 kB
/** * SocialData.tools user research handlers * Enhanced user analysis without API restrictions */ import { getSocialDataClient } from '../../socialDataClient.js'; import { SocialDataHandler, BulkUserProfilesArgs, UserGrowthAnalyticsArgs, UserInfluenceMetricsArgs } from '../../types/socialdata.js'; import { createSocialDataResponse, formatSocialDataError, formatUserList, formatAnalytics, createMissingApiKeyResponse } from '../../utils/socialdata-response.js'; export const handleBulkUserProfiles: SocialDataHandler<BulkUserProfilesArgs> = async ( _client: any, { usernames = [], userIds = [], includeMetrics = true }: BulkUserProfilesArgs ) => { try { const socialClient = getSocialDataClient(); if (!socialClient) { return createMissingApiKeyResponse('Bulk User Profiles'); } const profiles = []; // Process usernames for (const username of usernames) { try { const profile = await socialClient.getUserProfile({ username, includeMetrics }); profiles.push(profile.data); } catch (error) { console.warn(`Failed to get profile for username: ${username}`, error); } } // Process user IDs for (const userId of userIds) { try { const profile = await socialClient.getUserProfile({ userId, includeMetrics }); profiles.push(profile.data); } catch (error) { console.warn(`Failed to get profile for userId: ${userId}`, error); } } if (profiles.length === 0) { return createSocialDataResponse('No user profiles retrieved'); } return createSocialDataResponse( formatUserList(profiles, `Bulk User Profiles (${profiles.length} users)`) ); } catch (error) { throw new Error(formatSocialDataError(error as Error, 'bulk user profiles')); } }; export const handleUserGrowthAnalytics: SocialDataHandler<UserGrowthAnalyticsArgs> = async ( _client: any, { username, timeframe = 'weekly', period = 4 }: UserGrowthAnalyticsArgs ) => { try { const socialClient = getSocialDataClient(); if (!socialClient) { return createMissingApiKeyResponse('User Growth Analytics'); } // Get current profile const currentProfile = await socialClient.getUserProfile({ username, includeMetrics: true }); // Get recent tweets to analyze growth patterns const tweets = await socialClient.getUserTweets({ username, maxResults: 50 }); // Calculate basic growth metrics from available data const analytics = { user: { username: currentProfile.data.username, current_followers: currentProfile.data.public_metrics?.followers_count || 0, current_following: currentProfile.data.public_metrics?.following_count || 0, total_tweets: currentProfile.data.public_metrics?.tweet_count || 0 }, timeframe, period, recent_activity: { recent_tweets_count: tweets.data?.length || 0, avg_engagement: tweets.data ? tweets.data.reduce((sum: number, tweet: any) => sum + (tweet.public_metrics?.like_count || 0) + (tweet.public_metrics?.retweet_count || 0), 0) / tweets.data.length : 0 }, note: 'Growth analytics based on current snapshot and recent activity patterns' }; return createSocialDataResponse( formatAnalytics(analytics, `User Growth Analytics for @${username}`) ); } catch (error) { throw new Error(formatSocialDataError(error as Error, 'user growth analytics')); } }; export const handleUserInfluenceMetrics: SocialDataHandler<UserInfluenceMetricsArgs> = async ( _client: any, { username, analyzeEngagement = true, analyzeReach = true }: UserInfluenceMetricsArgs ) => { try { const socialClient = getSocialDataClient(); if (!socialClient) { return createMissingApiKeyResponse('User Influence Metrics'); } // Get user profile and recent tweets const [profile, tweets] = await Promise.all([ socialClient.getUserProfile({ username, includeMetrics: true }), socialClient.getUserTweets({ username, maxResults: 20 }) ]); const user = profile.data; const recentTweets = tweets.data || []; // Calculate influence metrics const metrics: any = { user: { username: user.username, followers: user.public_metrics?.followers_count || 0, following: user.public_metrics?.following_count || 0, verified: user.verified || false } }; if (analyzeEngagement && recentTweets.length > 0) { const totalLikes = recentTweets.reduce((sum: number, tweet: any) => sum + (tweet.public_metrics?.like_count || 0), 0); const totalRetweets = recentTweets.reduce((sum: number, tweet: any) => sum + (tweet.public_metrics?.retweet_count || 0), 0); const totalReplies = recentTweets.reduce((sum: number, tweet: any) => sum + (tweet.public_metrics?.reply_count || 0), 0); metrics.engagement = { avg_likes_per_tweet: Math.round(totalLikes / recentTweets.length), avg_retweets_per_tweet: Math.round(totalRetweets / recentTweets.length), avg_replies_per_tweet: Math.round(totalReplies / recentTweets.length), engagement_rate: user.public_metrics?.followers_count > 0 ? Math.round(((totalLikes + totalRetweets + totalReplies) / recentTweets.length / user.public_metrics.followers_count) * 10000) / 100 : 0 }; } if (analyzeReach) { metrics.reach = { follower_base: user.public_metrics?.followers_count || 0, potential_reach: user.public_metrics?.followers_count || 0, estimated_influence_score: Math.min(100, Math.log10((user.public_metrics?.followers_count || 1) + 1) * 20) }; } return createSocialDataResponse( formatAnalytics(metrics, `Influence Metrics for @${username}`) ); } catch (error) { throw new Error(formatSocialDataError(error as Error, 'user influence metrics')); } };

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/crazyrabbitLTC/mcp-twitter-server'

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