mcp twitter server

Local 2025-08-31 23:41:32 0

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.

Setup

  1. Clone the repository
  2. Install dependencies: npm install
  3. Copy .env.example to .env and fill in your Twitter API credentials
  4. Build the project: npm run build
  5. Start the server: npm start

Environment Variables

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

Available Tools

Tweet Operations

  • 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"
    }

Search & Analytics

  • 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"
    }

User Operations

  • 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"]
    }

Engagement

  • 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"]
    }

List Management

  • 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"]
    }

Error Handling

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

Response Format

All successful responses follow this format:

{
  "content": [
    {
      "type": "text",
      "text": "Operation result message"
    }
  ]
}

Development

  • Build: npm run build
  • Start: 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"
  }
]