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 build
npm start
Required 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 build
npm start
Watch 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"
}
]