Spaces:
Sleeping
Sleeping
| from mcp.server.fastmcp import FastMCP | |
| from fastmcp import Client | |
| from fastmcp.client.auth import OAuth | |
| import os | |
| from typing import Optional, Dict, Any | |
| mcp = FastMCP(name='EchoServer', stateless_http=True) | |
| # Twitter OAuth configuration | |
| TWITTER_CLIENT_ID = os.getenv('TWITTER_CLIENT_ID') | |
| TWITTER_CLIENT_SECRET = os.getenv('TWITTER_CLIENT_SECRET') | |
| TWITTER_REDIRECT_URI = os.getenv( | |
| 'TWITTER_REDIRECT_URI', 'http://localhost:8080/callback' | |
| ) | |
| # Global Twitter client instance | |
| twitter_client: Optional[Client] = None | |
| async def get_twitter_client() -> Client: | |
| """Get authenticated Twitter client using OAuth""" | |
| global twitter_client | |
| if twitter_client is None: | |
| # Configure OAuth for Twitter | |
| oauth = OAuth( | |
| mcp_url='https://api.twitter.com/2', # Twitter API v2 endpoint | |
| scopes=['tweet.read', 'tweet.write', 'users.read'], | |
| client_name='FastMCP Twitter Client', | |
| additional_client_metadata={ | |
| 'client_id': TWITTER_CLIENT_ID, | |
| 'client_secret': TWITTER_CLIENT_SECRET, | |
| 'redirect_uri': TWITTER_REDIRECT_URI | |
| } | |
| ) | |
| twitter_client = Client('https://api.twitter.com/2', auth=oauth) | |
| await twitter_client.__aenter__() | |
| return twitter_client | |
| def echo(message: str) -> str: | |
| return f'Echo: {message}' | |
| async def authenticate_twitter() -> Dict[str, Any]: | |
| """Authenticate with Twitter and return authentication status""" | |
| try: | |
| client = await get_twitter_client() | |
| # Test the connection by making a simple API call | |
| response = await client.request('GET', '/users/me') | |
| return { | |
| 'status': 'success', | |
| 'message': 'Successfully authenticated with Twitter', | |
| 'user_data': ( | |
| response.json() if hasattr(response, 'json') else str(response) | |
| ) | |
| } | |
| except Exception as e: | |
| return { | |
| 'status': 'error', | |
| 'message': f'Failed to authenticate with Twitter: {str(e)}', | |
| 'error': str(e) | |
| } | |
| async def post_tweet(text: str) -> Dict[str, Any]: | |
| """Post a tweet to Twitter""" | |
| try: | |
| client = await get_twitter_client() | |
| # Twitter API v2 endpoint for posting tweets | |
| tweet_data = { | |
| 'text': text | |
| } | |
| response = await client.request('POST', '/tweets', json=tweet_data) | |
| return { | |
| 'status': 'success', | |
| 'message': 'Tweet posted successfully', | |
| 'tweet_id': ( | |
| response.json().get('data', {}).get('id') | |
| if hasattr(response, 'json') else None | |
| ), | |
| 'response': ( | |
| response.json() if hasattr(response, 'json') else str(response) | |
| ) | |
| } | |
| except Exception as e: | |
| return { | |
| 'status': 'error', | |
| 'message': f'Failed to post tweet: {str(e)}', | |
| 'error': str(e) | |
| } | |
| async def get_twitter_profile() -> Dict[str, Any]: | |
| """Get the authenticated user's Twitter profile""" | |
| try: | |
| client = await get_twitter_client() | |
| # Get user profile information | |
| response = await client.request( | |
| 'GET', '/users/me?user.fields=id,name,username,public_metrics' | |
| ) | |
| return { | |
| 'status': 'success', | |
| 'message': 'Profile retrieved successfully', | |
| 'profile': ( | |
| response.json() if hasattr(response, 'json') else str(response) | |
| ) | |
| } | |
| except Exception as e: | |
| return { | |
| 'status': 'error', | |
| 'message': f'Failed to get profile: {str(e)}', | |
| 'error': str(e) | |
| } | |
| async def search_tweets(query: str, max_results: int = 10) -> Dict[str, Any]: | |
| """Search for tweets on Twitter""" | |
| try: | |
| client = await get_twitter_client() | |
| # Twitter API v2 search endpoint | |
| params = { | |
| 'query': query, | |
| 'max_results': min(max_results, 100), # Twitter API limit | |
| 'tweet.fields': 'created_at,author_id,public_metrics' | |
| } | |
| response = await client.request( | |
| 'GET', '/tweets/search/recent', params=params | |
| ) | |
| return { | |
| 'status': 'success', | |
| 'message': f'Found tweets for query: {query}', | |
| 'tweets': ( | |
| response.json() if hasattr(response, 'json') else str(response) | |
| ) | |
| } | |
| except Exception as e: | |
| return { | |
| 'status': 'error', | |
| 'message': f'Failed to search tweets: {str(e)}', | |
| 'error': str(e) | |
| } | |
| # Example usage functions | |
| async def example_twitter_oauth_usage(): | |
| """Example of how to use Twitter OAuth with FastMCP""" | |
| # Method 1: Using default OAuth settings | |
| async with Client('https://api.twitter.com/2', auth='oauth') as client: | |
| await client.ping() | |
| # Method 2: Using OAuth helper with custom configuration | |
| oauth = OAuth( | |
| mcp_url='https://api.twitter.com/2', | |
| scopes=['tweet.read', 'tweet.write', 'users.read'], | |
| client_name='FastMCP Twitter Client' | |
| ) | |
| async with Client('https://api.twitter.com/2', auth=oauth) as client: | |
| await client.ping() |