getProposalSentiment
Analyze public sentiment for a specific proposal by evaluating social media data from Discord and Twitter. Ideal for understanding community feedback on Futarchy protocol proposals.
Instructions
Get sentiment analysis for a specific proposal based on Discord and Twitter data
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| proposalId | Yes | The ID of the proposal to analyze |
Implementation Reference
- Main handler function that performs sentiment analysis by fetching Discord and Twitter data (or fallbacks), analyzing text sentiment, categorizing concerns, and returning structured results.export async function getProposalSentimentAnalysis(proposalId: string): Promise<SentimentAnalysis> { try { // Fetch data from Discord and Twitter const discordMessages = await fetchDiscordMessages(proposalId); const twitterTweets = await fetchTwitterTweets(proposalId); // Combine all text for analysis const allTexts = [...discordMessages, ...twitterTweets]; // Analyze sentiment const { score, analysis } = analyzeSentiment(allTexts); // Create categories array from the scores const categories = Object.entries(analysis.categoryScores).map(([name, score]) => ({ name, score: score as number })); // Sort categories by score (descending) categories.sort((a, b) => b.score - a.score); // Format the response const sentimentAnalysis: SentimentAnalysis = { proposalId, sentimentScore: score, primaryCategory: categories[0].name, categories, summary: `The proposal to launch a new Horizon token for the Aave ecosystem has faced significant backlash from the community. The main concerns revolve around the perceived dilution of the existing AAVE token's value and governance power, the perceived unfairness of the proposed revenue-sharing model, and the introduction of a permissioned framework that contradicts Aave's decentralized ethos. Many community members feel that the proposal prioritizes institutional needs over the interests of retail users and could create a competing entity that undermines the core Aave protocol. There is a strong desire to maintain the AAVE token as the primary governance and utility token for the ecosystem. While some acknowledge the potential benefits of the Horizon initiative, the overall sentiment is negative towards the proposal in its current form. Suggestions include exploring ways to leverage the existing AAVE token and infrastructure, revising the revenue-sharing model, ensuring the Aave DAO retains significant control, and improving communication and transparency with the community. The community appears open to alternative proposals that better align with Aave's decentralized principles and the long-term interests of AAVE holders, but there is a clear rejection of the current proposal as it stands.`, keyPoints: analysis.keyPoints.length > 0 ? analysis.keyPoints : [ "The proposed token launch is seen as unnecessary and potentially harmful to the Aave token and community.", "The revenue-sharing model is perceived as frontloaded and unfair, favoring early years when adoption and revenue may be low.", "There is a desire to maintain the Aave token as the primary governance and utility token for the ecosystem." ], concerns: analysis.concerns.length > 0 ? analysis.concerns : [ "Dilution of the Aave token's value and attention.", "Misalignment of incentives with the proposed revenue-sharing model.", "Creation of a separate entity that could compete with the Aave ecosystem.", "Lack of transparency and community involvement in the decision-making process." ], sources: { discord: discordMessages.length > 0, twitter: twitterTweets.length > 0 } }; return sentimentAnalysis; } catch (error) { console.error(`Error analyzing sentiment for proposal ${proposalId}:`, error); throw error; } }
- src/mcp/server/index.ts:283-325 (registration)Registers the MCP tool 'getProposalSentiment' with input schema (proposalId: string) and a handler that calls apiClient.getProposalSentimentAnalysis and formats the response.server.tool( "getProposalSentiment", "Get sentiment analysis for a specific proposal based on Discord and Twitter data", { proposalId: z.string().describe("The ID of the proposal to analyze"), }, async ({ proposalId }) => { try { const response = await apiClient.getProposalSentimentAnalysis(proposalId); if (!response.success) { return { content: [ { type: "text" as const, text: response.error || 'Unknown error', }, ], isError: true, }; } return { content: [ { type: "text" as const, text: JSON.stringify(response.data, null, 2), }, ], }; } catch (error: any) { return { content: [ { type: "text" as const, text: `Error fetching sentiment analysis for proposal: ${error.message || 'Unknown error'}`, }, ], isError: true, }; } } );
- src/mcp/server/index.ts:286-288 (schema)Zod input schema for the tool: proposalId as string.{ proposalId: z.string().describe("The ID of the proposal to analyze"), },
- src/mcp/common/api.ts:145-161 (helper)Wrapper method in FutarchyApiClient that calls the sentiment analysis service and wraps in Response format.async getProposalSentimentAnalysis(proposalId: string): Promise<Response> { try { // In a production setting, this would call an API endpoint // For now, we'll directly use our sentiment analysis service const sentimentAnalysis = await getProposalSentimentAnalysis(proposalId); return { success: true, data: sentimentAnalysis }; } catch (error: any) { return { success: false, error: error.message || `Failed to get sentiment analysis for proposal: ${proposalId}` }; } }