Library / SDK
xdevplatform/xmcp avatar
xdevplatform/xmcp

xmcp generates X API tools from the OpenAPI spec, minus streaming

MCP server for the X API

865 stars124 forksPythonLicense varies

At a glance

What is it?
xmcp is a small Python service that fetches the X API OpenAPI spec at startup and exposes its operations as FastMCP tools, with streaming and webhook endpoints filtered out and an allowlist to narrow the surface. It is a local developer tool rather than a production service, with tokens held only in memory.
Who is it for?
xmcp suits a developer who wants an LLM client to call the read side of the X API during local development, and who is comfortable with a tool surface generated from a spec rather than curated by hand. It is a poor choice for a hosted deployment, since tokens live in memory for the lifetime of the process and OAuth1 consent opens a browser on the server at startup.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The tool list is generated from a spec fetched at startup

The design is one sentence in the README: run a local MCP server that exposes the X API OpenAPI spec as tools using FastMCP. Nothing is hand written per endpoint. The server fetches the OpenAPI spec from https://api.twitter.com/2/openapi.json when it starts, reads the operations out of it, and registers each one as an MCP tool with FastMCP. That is why the repository can list roughly a hundred tool names, from getUsersByUsername and createPosts through getOpenApiSpec and getUsage, without a single hand-written wrapper per call. The consequence for a user is that the tool surface is whatever the upstream spec says it is on the day you start the server. A new X API endpoint appears as a new tool without a code change here, and a removed endpoint disappears the same way. The repository itself is six files at the top level, README.md, env.example, requirements.txt, server.py, test_grok_mcp.py and .gitignore, and the dependency list is short:

text
fastmcp
httpx
python-dotenv
requests-oauthlib
xai-sdk
xdk

FastMCP provides the server, httpx and requests-oauthlib handle the HTTP and OAuth work, python-dotenv loads configuration, and xdk is the X developer kit, with xai-sdk present for the optional Grok client.

Local setup is a virtualenv, a .env file and three tokens

The setup section is a numbered sequence, and the first step is a plain virtual environment:

bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Step two copies the example environment file:

bash
cp env.example .env

Three values are marked as required and the README says do not skip them: X_OAUTH_CONSUMER_KEY, X_OAUTH_CONSUMER_SECRET and X_BEARER_TOKEN, with a note that the bearer token is required for this setup and should be kept set even if you are using OAuth1. Everything else has a default. The OAuth1 callback settings default to host 127.0.0.1, port 8976, path /oauth/callback and a timeout of 300. Server settings default to base URL https://api.x.com, an API timeout of 30, MCP host 127.0.0.1, MCP port 8000 and X_API_DEBUG set to 1. Prerequisites are Python 3.9 or newer, an X Developer Platform app to get tokens, and optionally an xAI API key if you want to run the Grok test client.

Streaming and webhooks are removed from the generated surface

Two categories of endpoint never become tools, and the Notes section states the rule in three forms. Endpoints with /stream or /webhooks in the path are excluded. Operations tagged Stream or Webhooks in the spec are excluded. Operations marked with x-twitter-streaming: true are excluded. This filtering matters more than it might look, because the excluded operations are the ones whose result shape cannot be represented as a single tool response. A streaming endpoint delivers events over time, and a webhook endpoint is something you expose rather than call, so neither maps cleanly onto a request and response tool call. If you were hoping to read a live filtered stream through this server, the answer is that it is not in the tool list and the README does not describe a supported path for it. The filters are applied when the spec is loaded, so the same rule applies to any operation the X API adds later with those tags.

OAuth1 consent opens a browser when the server starts

The startup behaviour is the part that most affects how you use the tool locally. On startup, the server opens a browser for OAuth1 consent and waits for the callback. That means the machine running the server needs a desktop browser and a person to complete the consent, which is fine on a laptop and awkward on a remote box. The callback URL has to be registered in your X Developer App, and the README gives the format:

bash
http://127.0.0.1:8976/oauth/callback

Tokens are kept in memory only for the lifetime of the server process, so nothing is written to disk and a restart means repeating the consent flow. Two debugging switches exist for people who need to see what is happening: X_OAUTH_PRINT_TOKENS=1 prints tokens, and X_OAUTH_PRINT_AUTH_HEADER=1 prints request headers. Those are the sort of switches that should stay off on any shared machine, since the first one writes access credentials to standard output. Step four of the setup starts the server with python server.py, and the MCP endpoint is then http://127.0.0.1:8000/mcp by default. A local MCP client points at that address, and a remote client needs you to tunnel the local server, for example with ngrok, and use the public URL.

The allowlist is applied once, at startup

Because a generated surface can be large, there is a filter, and it is configured as a comma separated list in the environment:

bash
X_API_TOOL_ALLOWLIST=getUsersByUsername,createPosts,searchPostsRecent

The important operational detail is when it takes effect. Whitelisting is applied at startup when the OpenAPI spec is loaded, so the server must be restarted after any change to the list. There is no hot reload and no per-call filtering. The README also tells you to consult the full tool list before building an allowlist, and the list itself is published in the README under the heading for available tool calls, grouped by prefix so you can see at a glance that the write operations sit alongside the read ones. The choice of what to allow is a real decision rather than a formality. The list includes destructive and account level operations such as deletePosts, deleteAllConnections, deleteConnectionsByUuids, blockUsersDms, muteUser and unfollowUser, alongside the read operations, so an allowlist that only names the reads you intend to use is the safer starting point.

Optional OAuth2 token generation and the Grok test client

Two optional flows sit outside the main path. The first generates an OAuth2 user token, with CLIENT_ID and CLIENT_SECRET added to the .env, a redirect_uri updated in generate_authtoken.py to match the app settings, and then python generate_authtoken.py run interactively. The printed access token is copied into .env as X_OAUTH_ACCESS_TOKEN, and X_OAUTH_ACCESS_TOKEN_SECRET is stored if the flow returns a secret. The second is a Grok powered MCP client used to test the server from the other side. It needs XAI_API_KEY in the .env, a running local MCP server or a set MCP_SERVER_URL, and if Grok is not on your machine, an ngrok tunnel with MCP_SERVER_URL pointing at the public HTTPS URL ending in /mcp, for example ngrok http 8000 followed by MCP_SERVER_URL=https://<id>.ngrok-free.dev/mcp. The client itself is then started with python test_grok_mcp.py, with the model defaulting to grok-4-1-fast. Both flows are clearly optional extras for local experimentation rather than part of running the tools.

A local developer tool with a licence and release gap

Two facts belong in any evaluation. First, the maintenance picture. The last push to this repository was on 2026-04-09, and the repository publishes no GitHub releases, so there is no version history to track and no tag to pin against. A six month gap between the last commit and now is not a small detail for a tool that generates its tool list from a spec that changes upstream. Second, licensing is not stated. GitHub cannot classify a licence for this repository, and there is no LICENSE file among the six top level entries, so the default copyright rules apply to the code and you should treat reuse of server.py as unclear rather than assume a grant. There is a positive side too. The documentation is unusually complete for a project this size: prerequisites, an ordered setup with exact environment variable names and defaults, the callback registration format, the allowlist semantics with its startup caveat, the exclusion rules, the complete tool list, and both optional flows are all documented in one README, so nothing about running it requires reading source.

Editorial conclusion

xmcp suits a developer who wants an LLM client to call the read side of the X API during local development, and who is comfortable with a tool surface generated from a spec rather than curated by hand. It is a poor choice for a hosted deployment, since tokens live in memory for the lifetime of the process and OAuth1 consent opens a browser on the server at startup. Verify first that the endpoint you need is not one of the excluded /stream or /webhooks paths, that the generated tool name appears in the allowlist section of the README, and that the server can reach https://api.twitter.com/2/openapi.json, since the tool list is built from that fetch rather than from a bundled spec.

Frequently asked questions

How do I run the xmcp MCP server?

Create a virtual environment, install requirements.txt, copy env.example to .env and fill in X_OAUTH_CONSUMER_KEY, X_OAUTH_CONSUMER_SECRET and X_BEARER_TOKEN, then run python server.py. The MCP endpoint is then http://127.0.0.1:8000/mcp.

How does xmcp decide which X API endpoints become tools?

It fetches the OpenAPI spec from https://api.twitter.com/2/openapi.json at startup and turns the operations into FastMCP tools. Endpoints with /stream or /webhooks in the path, operations tagged Stream or Webhooks, and operations marked with x-twitter-streaming: true are excluded.

What does X_API_TOOL_ALLOWLIST do?

It restricts the server to a comma separated set of tool names, for example X_API_TOOL_ALLOWLIST=getUsersByUsername,createPosts,searchPostsRecent. The filter is applied at startup when the spec is loaded, so the server has to be restarted after any change.

Does xmcp keep OAuth tokens anywhere?

No. Tokens are kept in memory only for the lifetime of the server process, so restarting the server means completing the OAuth1 consent flow again. On startup the server opens a browser for OAuth1 consent and waits for the callback.

Can a remote MCP client connect to xmcp?

Yes, by tunnelling the local server, for example with ngrok, and pointing the remote client at the public URL. The README suggests ngrok http 8000 with MCP_SERVER_URL set to the public HTTPS URL ending in /mcp for the Grok test client.

Official sources

  1. Issues
  2. README
  3. xdevplatform/xmcp on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/xdevplatform-xmcp.svg)](https://hysenlabs.com/projects/xdevplatform-xmcp)

Was this useful?