mcp twitter server
Enables interaction with Twitter through a Model Context Protocol, allowing large language models to post tweets, search for tweets, and reply to tweets.
Enables interaction with Twitter through a Model Context Protocol, allowing large language models to post tweets, search for tweets, and reply to tweets.
A Model Context Protocol server implementation for Twitter API integration.
npm install.env.example to .env and fill in your Twitter API credentialsnpm run buildnpm startRequired Twitter API credentials in .env:
X_API_KEY=your_api_key
X_API_SECRET=your_api_secret
X_ACCESS_TOKEN=your_access_token
X_ACCESS_TOKEN_SECRET=your_access_token_secret
postTweet: Post a new tweet
{
"text": "Your tweet text here"
}
postTweetWithMedia: Post a tweet with media attachment
{
"text": "Your tweet text",
"mediaPath": "path/to/media/file",
"mediaType": "image/jpeg|image/png|image/gif|video/mp4",
"altText": "Optional alt text for accessibility"
}
getTweetById: Get a specific tweet by ID
{
"tweetId": "tweet_id",
"tweetFields": ["created_at", "public_metrics"]
}
replyToTweet: Reply to an existing tweet
{
"tweetId": "tweet_id",
"text": "Your reply text"
}
deleteTweet: Delete a tweet
{
"tweetId": "tweet_id"
}
searchTweets: Search for tweets
{
"query": "search query",
"maxResults": 10,
"tweetFields": ["created_at", "public_metrics"]
}
getHashtagAnalytics: Get analytics for a hashtag
{
"hashtag": "hashtag",
"startTime": "ISO-8601 date",
"endTime": "ISO-8601 date"
}
getUserInfo: Get user information
{
"username": "twitter_username",
"fields": ["description", "public_metrics"]
}
getUserTimeline: Get User is tweets
{
"username": "twitter_username",
"maxResults": 10,
"tweetFields": ["created_at", "public_metrics"]
}
getFollowers: Get User is followers
{
"username": "twitter_username",
"maxResults": 100,
"userFields": ["description", "public_metrics"]
}
getFollowing: Get accounts a user follows
{
"username": "twitter_username",
"maxResults": 100,
"userFields": ["description", "public_metrics"]
}
likeTweet: Like a tweet
{
"tweetId": "tweet_id"
}
unlikeTweet: Unlike a tweet
{
"tweetId": "tweet_id"
}
retweet: Retweet a tweet
{
"tweetId": "tweet_id"
}
undoRetweet: Undo a retweet
{
"tweetId": "tweet_id"
}
getRetweets: Get users who retweeted a tweet
{
"tweetId": "tweet_id",
"maxResults": 100,
"userFields": ["description", "public_metrics"]
}
getLikedTweets: Get tweets liked by a user
{
"userId": "user_id",
"maxResults": 100,
"tweetFields": ["created_at", "public_metrics"]
}
createList: Create a new list
{
"name": "List name",
"description": "List description",
"isPrivate": false
}
addUserToList: Add a user to a list
{
"listId": "list_id",
"username": "twitter_username"
}
removeUserFromList: Remove a user from a list
{
"listId": "list_id",
"username": "twitter_username"
}
getListMembers: Get members of a list
{
"listId": "list_id",
"maxResults": 100,
"userFields": ["description", "public_metrics"]
}
All tools return standardized error responses:
- Missing parameters: Missing required parameter: parameter_name
- API errors: Error message from Twitter API
- Not found errors: Appropriate "not found" message for the resource
All successful responses follow this format:
{
"content": [
{
"type": "text",
"text": "Operation result message"
}
]
}
npm run buildnpm startWatch mode: npm run dev
Here's a comprehensive status report of all Twitter tools:
## Working Tools (✓)
1. postTweet
Status: Working perfectly
Response: Returns tweet ID
Latest test: Success
2. getTweetById
Status: Working perfectly
Response: Returns complete tweet data
Latest test: Success
3. likeTweet & unlikeTweet
Status: Working perfectly
Response: Confirmation of action
Latest test: Success
4. retweet & undoRetweet
Status: Working perfectly
Response: Confirmation of action
Latest test: Success
5. replyToTweet
Status: Working perfectly
Response: Returns reply tweet ID
Latest test: Success
6. getUserInfo
Status: Working perfectly
Response: Complete user profile data
Latest test: Success
7. followUser & unfollowUser
Status: Working perfectly
Response: Confirmation of action
Latest test: Success
8. createList
Status: Working perfectly
Response: Confirmation of list creation
Latest test: Success
9. getUserLists
Status: Working perfectly
Response: Returns both owned and member lists
Latest test: Success
## Tools with Issues (⚠️)
1. getUserTimeline
Status: Error 400
Error: Invalid Request parameters
Fix needed: Parameter validation
2. searchTweets
Status: Error 400
Error: Invalid Request parameters
Fix needed: Query parameter formatting
3. getLikedTweets
Status: Error 400
Error: Invalid Request parameters
Fix needed: Parameter validation
## Missing Tools (❌)
- getHomeTimeline (not found in available tools)
- getFollowers (not available)
- getFollowing (not available)
- getHashtagAnalytics (not available)
## Priority Fixes Needed
1. Parameter Validation:
```typescript
// Implement for getUserTimeline, searchTweets, getLikedTweets
interface TwitterParamValidator {
validateTimelineParams(params: any): boolean;
validateSearchParams(params: any): boolean;
validateLikedTweetsParams(params: any): boolean;
}
Error Handling:
// Enhance error handling for 400 errors
interface TwitterErrorHandler {
handle400Error(endpoint: string, params: any): void;
logErrorDetails(error: any): void;
suggestParameterFixes(params: any): string[];
}
[
{
"description": "Post a tweet to Twitter",
"inputSchema": {
"properties": {
"text": {
"description": "The text of the tweet",
"type": "string"
}
},
"required": [
"text"
],
"type": "object"
},
"name": "postTweet"
},
{
"description": "Post a tweet with media attachment to Twitter",
"inputSchema": {
"properties": {
"altText": {
"description": "Alternative text for the media (accessibility)",
"type": "string"
},
"mediaPath": {
"description": "Local file path to the media to upload",
"type": "string"
},
"mediaType": {
"description": "MIME type of the media file",
"enum": [
"image/jpeg",
"image/png",
"image/gif",
"video/mp4"
],
"type": "string"
},
"text": {
"description": "The text of the tweet",
"type": "string"
}
},
"required": [
"text",
"mediaPath",
"mediaType"
],
"type": "object"
},
"name": "postTweetWithMedia"
},
{
"description": "Like a tweet by its ID",
"inputSchema": {
"properties": {
"tweetId": {
"description": "The ID of the tweet to like",
"type": "string"
}
},
"required": [
"tweetId"
],
"type": "object"
},
"name": "likeTweet"
},
{
"description": "Unlike a previously liked tweet",
"inputSchema": {
"properties": {
"tweetId": {
"description": "The ID of the tweet to unlike",
"type": "string"
}
},
"required": [
"tweetId"
],
"type": "object"
},
"name": "unlikeTweet"
},
{
"description": "Get a list of tweets liked by a user",
"inputSchema": {
"properties": {
"maxResults": {
"description": "The maximum number of results to return (default: 100, max: 100)",
"maximum": 100,
"minimum": 1,
"type": "number"
},
"tweetFields": {
"description": "Additional tweet fields to include in the response",
"items": {
"enum": [
"created_at",
"author_id",
"conversation_id",
"public_metrics",
"entities",
"context_annotations"
],
"type": "string"
},
"type": "array"
},
"userId": {
"description": "The ID of the user whose likes to fetch",
"type": "string"
}
},
"required": [
"userId"
],
"type": "object"
},
"name": "getLikedTweets"
},
{
"description": "Search for tweets using a query string",
"inputSchema": {
"properties": {
"maxResults": {
"description": "Maximum number of results to return",
"type": "number"
},
"query": {
"description": "The search query",
"type": "string"
},
"tweetFields": {
"description": "Fields to include in the tweet objects",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"query"
],
"type": "object"
},
"name": "searchTweets"
},
{
"description": "Reply to a tweet",
"inputSchema": {
"properties": {
"text": {
"description": "The text of the reply",
"type": "string"
},
"tweetId": {
"description": "The ID of the tweet to reply to",
"type": "string"
}
},
"required": [
"tweetId",
"text"
],
"type": "object"
},
"name": "replyToTweet"
},
{
"description": "Get recent tweets from a user timeline",
"inputSchema": {
"properties": {
"expansions": {
"description": "Additional fields to expand in the response",
"items": {
"enum": [
"author_id",
"referenced_tweets.id",
"in_reply_to_user_id",
"attachments.media_keys"
],
"type": "string"
},
"type": "array"
},
"maxResults": {
"description": "Maximum number of results to return",
"type": "number"
},
"tweetFields": {
"description": "Fields to include in the tweet objects",
"items": {
"enum": [
"created_at",
"author_id",
"conversation_id",
"public_metrics",
"entities",
"context_annotations"
],
"type": "string"
},
"type": "array"
},
"userFields": {
"description": "User fields to include in the response",
"items": {
"enum": [
"username",
"name",
"profile_image_url",
"verified"
],
"type": "string"
},
"type": "array"
},
"userId": {
"description": "The ID of the user",
"type": "string"
}
},
"required": [
"userId"
],
"type": "object"
},
"name": "getUserTimeline"
},
{
"description": "Get a tweet by its ID",
"inputSchema": {
"properties": {
"tweetFields": {
"description": "Fields to include in the tweet object",
"items": {
"type": "string"
},
"type": "array"
},
"tweetId": {
"description": "The ID of the tweet",
"type": "string"
}
},
"required": [
"tweetId"
],
"type": "object"
},
"name": "getTweetById"
},
{
"description": "Get information about a Twitter user",
"inputSchema": {
"properties": {
"username": {
"description": "The username of the user",
"type": "string"
}
},
"required": [
"username"
],
"type": "object"
},
"name": "getUserInfo"
},
{
"description": "Get multiple tweets by their IDs",
"inputSchema": {
"properties": {
"tweetFields": {
"description": "Additional tweet fields to include in the response",
"items": {
"enum": [
"created_at",
"author_id",
"conversation_id",
"public_metrics",
"entities",
"context_annotations"
],
"type": "string"
},
"type": "array"
},
"tweetIds": {
"description": "Array of tweet IDs to fetch",
"items": {
"type": "string"
},
"maxItems": 100,
"type": "array"
}
},
"required": [
"tweetIds"
],
"type": "object"
},
"name": "getTweetsByIds"
},
{
"description": "Retweet a tweet by its ID",
"inputSchema": {
"properties": {
"tweetId": {
"description": "The ID of the tweet to retweet",
"type": "string"
}
},
"required": [
"tweetId"
],
"type": "object"
},
"name": "retweet"
},
{
"description": "Undo a retweet by its ID",
"inputSchema": {
"properties": {
"tweetId": {
"description": "The ID of the tweet to un-retweet",
"type": "string"
}
},
"required": [
"tweetId"
],
"type": "object"
},
"name": "undoRetweet"
},
{
"description": "Get a list of retweets of a tweet",
"inputSchema": {
"properties": {
"maxResults": {
"description": "The maximum number of results to return (default: 100, max: 100)",
"maximum": 100,
"minimum": 1,
"type": "number"
},
"tweetId": {
"description": "The ID of the tweet to get retweets for",
"type": "string"
},
"userFields": {
"description": "Additional user fields to include in the response",
"items": {
"enum": [
"description",
"profile_image_url",
"public_metrics",
"verified"
],
"type": "string"
},
"type": "array"
}
},
"required": [
"tweetId"
],
"type": "object"
},
"name": "getRetweets"
},
{
"description": "Follow a user by their username",
"inputSchema": {
"properties": {
"username": {
"description": "The username of the user to follow",
"type": "string"
}
},
"required": [
"username"
],
"type": "object"
},
"name": "followUser"
},
{
"description": "Unfollow a user by their username",
"inputSchema": {
"properties": {
"username": {
"description": "The username of the user to unfollow",
"type": "string"
}
},
"required": [
"username"
],
"type": "object"
},
"name": "unfollowUser"
},
{
"description": "Get followers of a user",
"inputSchema": {
"properties": {
"maxResults": {
"description": "Maximum number of followers to return",
"type": "number"
},
"userFields": {
"description": "Fields to include in the user objects",
"items": {
"type": "string"
},
"type": "array"
},
"username": {
"description": "The username of the account",
"type": "string"
}
},
"required": [
"username"
],
"type": "object"
},
"name": "getFollowers"
},
{
"description": "Get a list of users that a user is following",
"inputSchema": {
"properties": {
"maxResults": {
"description": "The maximum number of results to return (default: 100, max: 1000)",
"maximum": 1000,
"minimum": 1,
"type": "number"
},
"userFields": {
"description": "Additional user fields to include in the response",
"items": {
"enum": [
"description",
"profile_image_url",
"public_metrics",
"verified",
"location",
"url"
],
"type": "string"
},
"type": "array"
},
"username": {
"description": "The username of the user whose following list to fetch",
"type": "string"
}
},
"required": [
"username"
],
"type": "object"
},
"name": "getFollowing"
},
{
"description": "Create a new Twitter list",
"inputSchema": {
"properties": {
"description": {
"description": "A description of the list",
"type": "string"
},
"name": {
"description": "The name of the list",
"type": "string"
},
"private": {
"description": "Whether the list should be private",
"type": "boolean"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "createList"
},
{
"description": "Add a user to a Twitter list",
"inputSchema": {
"properties": {
"listId": {
"description": "The ID of the list",
"type": "string"
},
"username": {
"description": "The username of the user to add",
"type": "string"
}
},
"required": [
"listId",
"username"
],
"type": "object"
},
"name": "addUserToList"
},
{
"description": "Remove a user from a Twitter list",
"inputSchema": {
"properties": {
"listId": {
"description": "The ID of the list",
"type": "string"
},
"username": {
"description": "The username of the user to remove",
"type": "string"
}
},
"required": [
"listId",
"username"
],
"type": "object"
},
"name": "removeUserFromList"
},
{
"description": "Get members of a Twitter list",
"inputSchema": {
"properties": {
"listId": {
"description": "The ID of the list",
"type": "string"
},
"maxResults": {
"description": "The maximum number of results to return (default: 100, max: 100)",
"maximum": 100,
"minimum": 1,
"type": "number"
},
"userFields": {
"description": "Additional user fields to include in the response",
"items": {
"enum": [
"description",
"profile_image_url",
"public_metrics",
"verified",
"location",
"url"
],
"type": "string"
},
"type": "array"
}
},
"required": [
"listId"
],
"type": "object"
},
"name": "getListMembers"
},
{
"description": "Get lists owned by a user",
"inputSchema": {
"properties": {
"listFields": {
"description": "Additional list fields to include in the response",
"items": {
"enum": [
"created_at",
"follower_count",
"member_count",
"private",
"description"
],
"type": "string"
},
"type": "array"
},
"maxResults": {
"description": "The maximum number of results to return (default: 100, max: 100)",
"maximum": 100,
"minimum": 1,
"type": "number"
},
"username": {
"description": "The username of the user whose lists to fetch",
"type": "string"
}
},
"required": [
"username"
],
"type": "object"
},
"name": "getUserLists"
},
{
"description": "Get analytics for a specific hashtag",
"inputSchema": {
"properties": {
"endTime": {
"description": "End time for the analysis (ISO 8601)",
"type": "string"
},
"hashtag": {
"description": "The hashtag to analyze (with or without #)",
"type": "string"
},
"startTime": {
"description": "Start time for the analysis (ISO 8601)",
"type": "string"
}
},
"required": [
"hashtag"
],
"type": "object"
},
"name": "getHashtagAnalytics"
},
{
"description": "Delete a tweet by its ID",
"inputSchema": {
"properties": {
"tweetId": {
"description": "The ID of the tweet to delete",
"type": "string"
}
},
"required": [
"tweetId"
],
"type": "object"
},
"name": "deleteTweet"
}
]