Skip to main content
Glama
crazyrabbitLTC

Twitter MCP Server

analyzeSentiment

Evaluate sentiment in tweets by analyzing text matching a search query; includes keyword frequency and customizable sample size for insights into public opinion.

Instructions

Perform sentiment analysis on tweets matching a query

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
includeKeywordsNoInclude keyword frequency analysis (default: true)
queryYesSearch query for sentiment analysis
sampleSizeNoNumber of tweets to analyze (default: 50)

Implementation Reference

  • Main handler function implementing the analyzeSentiment tool. Performs keyword-based sentiment analysis on tweets retrieved via search query.
    export const handleAnalyzeSentiment: SocialDataHandler<SentimentAnalysisArgs> = async ( _client: any, { query, sampleSize = 50, includeKeywords = true }: SentimentAnalysisArgs ) => { try { const socialClient = getSocialDataClient(); if (!socialClient) { return createMissingApiKeyResponse('Sentiment Analysis'); } const result = await socialClient.searchTweets({ query, maxResults: sampleSize }); const tweets = result.data || []; if (tweets.length === 0) { return createSocialDataResponse(`No tweets found for sentiment analysis: ${query}`); } // Simple sentiment analysis based on keywords const positiveKeywords = ['good', 'great', 'awesome', 'love', 'amazing', 'excellent', 'perfect', 'happy', 'wonderful', '❤️', '😊', '👍', '🎉']; const negativeKeywords = ['bad', 'terrible', 'awful', 'hate', 'horrible', 'worst', 'disgusting', 'angry', 'sad', '😡', '😢', '👎', '💔']; let positive = 0, negative = 0, neutral = 0; const sentimentBreakdown = tweets.map((tweet: any) => { const text = tweet.text?.toLowerCase() || ''; const positiveCount = positiveKeywords.filter(word => text.includes(word)).length; const negativeCount = negativeKeywords.filter(word => text.includes(word)).length; let sentiment: string; if (positiveCount > negativeCount) { sentiment = 'positive'; positive++; } else if (negativeCount > positiveCount) { sentiment = 'negative'; negative++; } else { sentiment = 'neutral'; neutral++; } return { tweet_id: tweet.id_str, text: tweet.text?.substring(0, 150), sentiment, confidence: Math.max(positiveCount, negativeCount) > 0 ? 'medium' : 'low', engagement: (tweet.favorite_count || 0) + (tweet.retweet_count || 0) }; }); let keywordAnalysis = {}; if (includeKeywords) { const allText = tweets.map((t: any) => t.text).join(' ').toLowerCase(); const words = allText.match(/\b\w+\b/g) || []; const wordFreq = words.reduce((freq: any, word: string) => { if (word.length > 3) { freq[word] = (freq[word] || 0) + 1; } return freq; }, {}); keywordAnalysis = { top_keywords: Object.entries(wordFreq) .sort(([,a], [,b]) => (b as number) - (a as number)) .slice(0, 10) .map(([word, count]) => ({ word, count })), positive_indicators: positiveKeywords.filter(word => allText.includes(word)), negative_indicators: negativeKeywords.filter(word => allText.includes(word)) }; } const sentimentAnalysis = { query, sample_size: tweets.length, analysis_date: new Date().toISOString(), sentiment_distribution: { positive: { count: positive, percentage: Math.round((positive / tweets.length) * 100) }, negative: { count: negative, percentage: Math.round((negative / tweets.length) * 100) }, neutral: { count: neutral, percentage: Math.round((neutral / tweets.length) * 100) } }, overall_sentiment: positive > negative ? 'Positive' : negative > positive ? 'Negative' : 'Neutral', confidence_level: tweets.length > 30 ? 'High' : tweets.length > 10 ? 'Medium' : 'Low', keyword_analysis: keywordAnalysis, sample_tweets: { most_positive: sentimentBreakdown.filter(t => t.sentiment === 'positive') .sort((a, b) => b.engagement - a.engagement)[0], most_negative: sentimentBreakdown.filter(t => t.sentiment === 'negative') .sort((a, b) => b.engagement - a.engagement)[0] } }; return createSocialDataResponse( formatAnalytics(sentimentAnalysis, `Sentiment Analysis: "${query}"`) ); } catch (error) { throw new Error(formatSocialDataError(error as Error, 'sentiment analysis')); } };
  • TypeScript interface defining the input arguments for the sentiment analysis handler.
    interface SentimentAnalysisArgs { query: string; sampleSize?: number; includeKeywords?: boolean; }
  • MCP tool schema definition including description and input validation schema for analyzeSentiment.
    analyzeSentiment: { description: 'Perform sentiment analysis on tweets matching a query', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query for sentiment analysis' }, sampleSize: { type: 'number', description: 'Number of tweets to analyze (default: 50)', minimum: 10, maximum: 200 }, includeKeywords: { type: 'boolean', description: 'Include keyword frequency analysis (default: true)' } }, required: ['query'] } },
  • src/index.ts:494-497 (registration)
    Dispatch/registration of the analyzeSentiment tool in the main MCP server request handler switch statement.
    case 'analyzeSentiment': { const args = request.params.arguments as any; response = await handleAnalyzeSentiment(client, args); break;
  • src/index.ts:81-83 (registration)
    Import of the handleAnalyzeSentiment handler function into the main index.ts for tool dispatching.
    handleAnalyzeSentiment, handleTrackVirality } from './handlers/socialdata/index.js';

Latest Blog Posts

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