Run a local MCP server that exposes the X API OpenAPI spec as tools using FastMCP. Streaming and webhook endpoints are excluded.
- Python 3.9+
- An X Developer Platform app (to get tokens)
- Optional: an xAI API key if you want to run the Grok test client
- Create a virtual environment and install dependencies:
python -m venv .venvsource .venv/bin/activatepip install -r requirements.txt
- Create your local
.env:cp env.example .env- Required values (do not skip):
X_OAUTH_CONSUMER_KEYX_OAUTH_CONSUMER_SECRETX_BEARER_TOKEN(required for this setup; keep it set even if using OAuth1)
- OAuth1 callback (defaults are fine):
X_OAUTH_CALLBACK_HOST(default127.0.0.1)X_OAUTH_CALLBACK_PORT(default8976)X_OAUTH_CALLBACK_PATH(default/oauth/callback)X_OAUTH_CALLBACK_TIMEOUT(default300)
- Server settings (optional):
X_API_BASE_URL(defaulthttps://api.x.com)X_API_TIMEOUT(default30)X_API_AUTH_MODE(defaultoauth1; setoauth2for OAuth2 Bearer user context)MCP_HOST(default127.0.0.1)MCP_PORT(default8000)X_API_DEBUG(default1)
- Tool filtering (optional, comma-separated):
X_API_TOOL_ALLOWLIST
- Optional Grok test client:
XAI_API_KEYXAI_MODEL(defaultgrok-4-1-fast)MCP_SERVER_URL(defaulthttp://127.0.0.1:8000/mcp)
- Optional OAuth2 token generation:
X_OAUTH2_CLIENT_ID(CLIENT_IDis also accepted)X_OAUTH2_CLIENT_SECRET(CLIENT_SECRETis also accepted)CLIENT_IDCLIENT_SECRETX_OAUTH2_SCOPESX_OAUTH2_CALLBACK_URLX_OAUTH2_ACCESS_TOKENX_OAUTH2_REFRESH_TOKENX_OAUTH2_REFRESH_ON_START
- Optional OAuth1 debug output:
X_OAUTH_PRINT_TOKENSX_OAUTH_PRINT_AUTH_HEADER
- Register the callback URL in your X Developer App:
http://<X_OAUTH_CALLBACK_HOST>:<X_OAUTH_CALLBACK_PORT><X_OAUTH_CALLBACK_PATH>
Example (defaults):
http://127.0.0.1:8976/oauth/callback
- Start the server:
python server.py
The MCP endpoint is http://127.0.0.1:8000/mcp by default.
- Connect an MCP client:
- Local client: point it to
http://127.0.0.1:8000/mcp. - Remote client: tunnel your local server (e.g., ngrok) and use the public URL.
Use X_API_TOOL_ALLOWLIST to load a small, explicit set of tools:
X_API_TOOL_ALLOWLIST=getUsersByUsername,createPosts,searchPostsRecent
Whitelisting is applied at startup when the OpenAPI spec is loaded, so restart the server after changes. See the full tool list below before building your allowlist.
On startup, the server opens a browser for OAuth1 consent and waits for the
callback. Tokens are kept in memory only for the lifetime of the server
process. Set X_OAUTH_PRINT_TOKENS=1 to print tokens, or
X_OAUTH_PRINT_AUTH_HEADER=1 to print request headers.
Some X API endpoints, including Post analytics endpoints, require OAuth2 user
context. Set X_API_AUTH_MODE=oauth2 and provide an OAuth2 user access token in
X_OAUTH2_ACCESS_TOKEN.
When X_OAUTH2_REFRESH_TOKEN is set, the server refreshes the OAuth2 access
token on startup by default and writes the new token back to .env. Disable
this with X_OAUTH2_REFRESH_ON_START=0.
Below is the full list of tool calls you can whitelist via
X_API_TOOL_ALLOWLIST. Copy any of these into your .env allowlist.
addListsMemberaddUserPublicKeyappendMediaUploadblockUsersDmscreateCommunityNotescreateComplianceJobscreateDirectMessagesByConversationIdcreateDirectMessagesByParticipantIdcreateDirectMessagesConversationcreateListscreateMediaMetadatacreateMediaSubtitlescreatePostscreateUsersBookmarkdeleteActivitySubscriptiondeleteAllConnectionsdeleteCommunityNotesdeleteConnectionsByEndpointdeleteConnectionsByUuidsdeleteDirectMessagesEventsdeleteListsdeleteMediaSubtitlesdeletePostsdeleteUsersBookmarkevaluateCommunityNotesfinalizeMediaUploadfollowListfollowUsergetAccountActivitySubscriptionCountgetActivitySubscriptionsgetChatConversationgetChatConversationsgetCommunitiesByIdgetComplianceJobsgetComplianceJobsByIdgetConnectionHistorygetDirectMessagesEventsgetDirectMessagesEventsByConversationIdgetDirectMessagesEventsByIdgetDirectMessagesEventsByParticipantIdgetInsights28HrgetInsightsHistoricalgetListsByIdgetListsFollowersgetListsMembersgetListsPostsgetMarketplaceHandleAvailabilitygetMediaAnalyticsgetMediaByMediaKeygetMediaByMediaKeysgetMediaUploadStatusgetNewsgetOpenApiSpecgetPostsAnalyticsgetPostsByIdgetPostsByIdsgetPostsCountsAllgetPostsCountsRecentgetPostsLikingUsersgetPostsQuotedPostsgetPostsRepostedBygetPostsRepostsgetSpacesBuyersgetSpacesByCreatorIdsgetSpacesByIdgetSpacesByIdsgetSpacesPostsgetTrendsByWoeidgetTrendsPersonalizedTrendsgetUsagegetUserPublicKeysgetUsersAffiliatesgetUsersBlockinggetUsersBookmarkFoldersgetUsersBookmarksgetUsersBookmarksByFolderIdgetUsersByIdgetUsersByIdsgetUsersByUsernamegetUsersByUsernamesgetUsersFollowedListsgetUsersFollowersgetUsersFollowinggetUsersLikedPostsgetUsersListMembershipsgetUsersMegetUsersMentionsgetUsersMutinggetUsersOwnedListsgetUsersPinnedListsgetUsersPostsgetUsersRepostsOfMegetUsersTimelinehidePostsReplyinitializeMediaUploadlikePostmediaUploadmuteUserpinListremoveListsMemberByUserIdrepostPostsearchCommunitiessearchCommunityNotesWrittensearchEligiblePostssearchNewssearchPostsAllsearchPostsRecentsearchSpacessearchUserssendChatMessageunblockUsersDmsunfollowListunfollowUserunlikePostunmuteUserunpinListunrepostPostupdateActivitySubscriptionupdateLists
- Add
X_OAUTH2_CLIENT_IDandX_OAUTH2_CLIENT_SECRETto your.env. ExistingCLIENT_IDandCLIENT_SECRETvalues are also accepted. - Confirm the OAuth2 callback URL in your X Developer App matches
http://127.0.0.1:8976/oauth/callback, or setX_OAUTH2_CALLBACK_URL. - Set scopes in
X_OAUTH2_SCOPES. For analytics collection, use at leasttweet.read users.read offline.access. - Run
python generate_oauth2_token.pyand approve access in X. - The script saves
X_API_AUTH_MODE=oauth2,X_OAUTH2_ACCESS_TOKEN, andX_OAUTH2_REFRESH_TOKENto.env.
- Set
XAI_API_KEYin.env. - Make sure your MCP server is running locally (or set
MCP_SERVER_URL). - If Grok is not running on your machine, use ngrok to expose your local MCP
server and set
MCP_SERVER_URLto the public HTTPS URL that ends with/mcp. Example flow:ngrok http 8000thenMCP_SERVER_URL=https://<id>.ngrok-free.dev/mcp. - Run
python test_grok_mcp.py.
- Endpoints with
/streamor/webhooksin the path are excluded. - Operations tagged
StreamorWebhooks, or marked withx-twitter-streaming: true, are excluded. - The OpenAPI spec is fetched from
https://api.twitter.com/2/openapi.jsonat startup.