xmcp/README.md
2026-02-06 10:35:21 -08:00

240 lines
6.6 KiB
Markdown

# X API FastMCP Server
Run a local MCP server that exposes the X API OpenAPI spec as tools using
FastMCP. Streaming and webhook endpoints are excluded.
## Prerequisites
- 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
## Setup (local)
1. Create a virtual environment and install dependencies:
- `python -m venv .venv`
- `source .venv/bin/activate`
- `pip install -r requirements.txt`
2. Create your local `.env`:
- `cp env.example .env`
- Required values (do not skip):
- `X_OAUTH_CONSUMER_KEY`
- `X_OAUTH_CONSUMER_SECRET`
- `X_BEARER_TOKEN` (required for this setup; keep it set even if using OAuth1)
- OAuth1 callback (defaults are fine):
- `X_OAUTH_CALLBACK_HOST` (default `127.0.0.1`)
- `X_OAUTH_CALLBACK_PORT` (default `8976`)
- `X_OAUTH_CALLBACK_PATH` (default `/oauth/callback`)
- `X_OAUTH_CALLBACK_TIMEOUT` (default `300`)
- Server settings (optional):
- `X_API_BASE_URL` (default `https://api.x.com`)
- `X_API_TIMEOUT` (default `30`)
- `MCP_HOST` (default `127.0.0.1`)
- `MCP_PORT` (default `8000`)
- `X_API_DEBUG` (default `1`)
- Tool filtering (optional, comma-separated):
- `X_API_TOOL_ALLOWLIST`
- Optional Grok test client:
- `XAI_API_KEY`
- `XAI_MODEL` (default `grok-4-1-fast`)
- `MCP_SERVER_URL` (default `http://127.0.0.1:8000/mcp`)
- Optional OAuth2 token generation:
- `CLIENT_ID`
- `CLIENT_SECRET`
- `X_OAUTH_ACCESS_TOKEN`
- `X_OAUTH_ACCESS_TOKEN_SECRET` (optional)
- Optional OAuth1 debug output:
- `X_OAUTH_PRINT_TOKENS`
- `X_OAUTH_PRINT_AUTH_HEADER`
3. 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
```
4. Start the server:
```
python server.py
```
The MCP endpoint is `http://127.0.0.1:8000/mcp` by default.
5. 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.
## Whitelisting tools
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.
## OAuth1 flow (startup behavior)
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.
## Available tool calls (allowlist-ready)
Below is the full list of tool calls you can whitelist via
`X_API_TOOL_ALLOWLIST`. Copy any of these into your `.env` allowlist.
- `addListsMember`
- `addUserPublicKey`
- `appendMediaUpload`
- `blockUsersDms`
- `createCommunityNotes`
- `createComplianceJobs`
- `createDirectMessagesByConversationId`
- `createDirectMessagesByParticipantId`
- `createDirectMessagesConversation`
- `createLists`
- `createMediaMetadata`
- `createMediaSubtitles`
- `createPosts`
- `createUsersBookmark`
- `deleteActivitySubscription`
- `deleteAllConnections`
- `deleteCommunityNotes`
- `deleteConnectionsByEndpoint`
- `deleteConnectionsByUuids`
- `deleteDirectMessagesEvents`
- `deleteLists`
- `deleteMediaSubtitles`
- `deletePosts`
- `deleteUsersBookmark`
- `evaluateCommunityNotes`
- `finalizeMediaUpload`
- `followList`
- `followUser`
- `getAccountActivitySubscriptionCount`
- `getActivitySubscriptions`
- `getChatConversation`
- `getChatConversations`
- `getCommunitiesById`
- `getComplianceJobs`
- `getComplianceJobsById`
- `getConnectionHistory`
- `getDirectMessagesEvents`
- `getDirectMessagesEventsByConversationId`
- `getDirectMessagesEventsById`
- `getDirectMessagesEventsByParticipantId`
- `getInsights28Hr`
- `getInsightsHistorical`
- `getListsById`
- `getListsFollowers`
- `getListsMembers`
- `getListsPosts`
- `getMarketplaceHandleAvailability`
- `getMediaAnalytics`
- `getMediaByMediaKey`
- `getMediaByMediaKeys`
- `getMediaUploadStatus`
- `getNews`
- `getOpenApiSpec`
- `getPostsAnalytics`
- `getPostsById`
- `getPostsByIds`
- `getPostsCountsAll`
- `getPostsCountsRecent`
- `getPostsLikingUsers`
- `getPostsQuotedPosts`
- `getPostsRepostedBy`
- `getPostsReposts`
- `getSpacesBuyers`
- `getSpacesByCreatorIds`
- `getSpacesById`
- `getSpacesByIds`
- `getSpacesPosts`
- `getTrendsByWoeid`
- `getTrendsPersonalizedTrends`
- `getUsage`
- `getUserPublicKeys`
- `getUsersAffiliates`
- `getUsersBlocking`
- `getUsersBookmarkFolders`
- `getUsersBookmarks`
- `getUsersBookmarksByFolderId`
- `getUsersById`
- `getUsersByIds`
- `getUsersByUsername`
- `getUsersByUsernames`
- `getUsersFollowedLists`
- `getUsersFollowers`
- `getUsersFollowing`
- `getUsersLikedPosts`
- `getUsersListMemberships`
- `getUsersMe`
- `getUsersMentions`
- `getUsersMuting`
- `getUsersOwnedLists`
- `getUsersPinnedLists`
- `getUsersPosts`
- `getUsersRepostsOfMe`
- `getUsersTimeline`
- `hidePostsReply`
- `initializeMediaUpload`
- `likePost`
- `mediaUpload`
- `muteUser`
- `pinList`
- `removeListsMemberByUserId`
- `repostPost`
- `searchCommunities`
- `searchCommunityNotesWritten`
- `searchEligiblePosts`
- `searchNews`
- `searchPostsAll`
- `searchPostsRecent`
- `searchSpaces`
- `searchUsers`
- `sendChatMessage`
- `unblockUsersDms`
- `unfollowList`
- `unfollowUser`
- `unlikePost`
- `unmuteUser`
- `unpinList`
- `unrepostPost`
- `updateActivitySubscription`
- `updateLists`
## Generate an OAuth2 user token (optional)
1. Add `CLIENT_ID` and `CLIENT_SECRET` to your `.env`.
2. Update `redirect_uri` in `generate_authtoken.py` to match your app settings.
3. Run `python generate_authtoken.py` and follow the prompts.
4. Copy the printed access token into `.env` as `X_OAUTH_ACCESS_TOKEN`.
If your flow returns a secret, store it as `X_OAUTH_ACCESS_TOKEN_SECRET`.
## Run the Grok MCP test client (optional)
1. Set `XAI_API_KEY` in `.env`.
2. Make sure your MCP server is running locally (or set `MCP_SERVER_URL`).
3. If Grok is not running on your machine, use ngrok to expose your local MCP
server and set `MCP_SERVER_URL` to the public HTTPS URL that ends with `/mcp`.
Example flow: `ngrok http 8000` then `MCP_SERVER_URL=https://<id>.ngrok-free.dev/mcp`.
4. Run `python test_grok_mcp.py`.
## Notes
- Endpoints with `/stream` or `/webhooks` in the path are excluded.
- Operations tagged `Stream` or `Webhooks`, or marked with
`x-twitter-streaming: true`, are excluded.
- The OpenAPI spec is fetched from `https://api.twitter.com/2/openapi.json` at
startup.