x-agent MCP Server
by toxxxaka
README.md
# X-agent
[](https://github.com/toxxxaka/x-agent/actions/workflows/ci.yml)
[](https://www.python.org/)
[](LICENSE)
Private, self-hosted X publishing automation built around the authenticated X web UI.
x-agent lets an AI assistant or local operator publish reviewed posts, linear threads, replies, and Community posts through Playwright. It does not require X API credits and keeps the authenticated browser session on infrastructure you control.
> This is browser automation, not an official X API client. X may change its UI, authentication behaviour, or terms at any time. Use it only with an account you control and in accordance with X's rules.
## Capabilities
- Publish one final, approved X post.
- Publish a linear thread: root post followed by sequential replies.
- Reply to an ordinary or Community post.
- Select an X Community by exact name, with fail-closed verification.
- List Communities available to the current account without publishing.
- Attach one image to a post or to the root of a thread.
- Use the project through CLI, stdio MCP, or bearer-protected Streamable HTTP MCP.
## Architecture
```text
Chat or local operator
|
+-- CLI
+-- MCP stdio
+-- Streamable HTTP MCP (Bearer token)
|
v
x_agent.posts
|
Playwright and Chromium
|
authenticated X cookie session
|
x.com
```
The chat agent drafts and obtains explicit approval. The execution layer receives only final text and performs the external action. x_agent/posts.py owns browser interaction, audience selection, media verification, reply chaining, and sanitized diagnostics.
## Safety model
Publishing is an external side effect and must happen only after explicit approval of the final draft.
The implementation fails closed:
- A requested Community must be uniquely matched, selected, and confirmed. Failure never falls back to Everyone.
- A requested image must produce both an X composer preview and a successful upload response. Otherwise Post is never clicked.
- A thread stops at the first failed reply and reports already-published URLs; it never continues blindly.
## Repository layout
```text
x_agent/
browser.py Browser setup, cookies, authentication checks
cookies.py Cookie-file handling
posts.py Posts, replies, threads, Communities, media verification
cli.py stdin-based command-line interface
mcp_server.py Dependency-free stdio MCP server
mcp_http.py Streamable HTTP MCP server with bearer authentication
debug.py Sanitized file logging
systemd/ Example service units
tests/ Unit tests
*.env.example Configuration templates; no secrets
```
Historical experiments, local backups, logs, screenshots, cookies, virtual environments, and environment files are deployment artefacts, not production source.
## Prerequisites
- Linux with Python 3.11+.
- Playwright and Chromium or Chrome.
- An X account authenticated in a browser session you control.
- A cookie export available only on the deployment host.
Example setup:
```bash
python3 -m venv venv
./venv/bin/pip install playwright mcp uvicorn starlette
./venv/bin/playwright install chromium
```
## Session cookies
Store the cookie export outside the repository, for example:
```text
/opt/x-agent/x_cookies.json
```
Protect it:
```bash
sudo chown root:root /opt/x-agent/x_cookies.json
sudo chmod 600 /opt/x-agent/x_cookies.json
```
Never commit cookies, tokens, browser profiles, logs, screenshots, or .env files. Refresh the cookie export from a trusted browser session when x_status reports an expired session.
## CLI
The CLI reads text from standard input rather than process arguments.
```bash
PYTHONPATH=/opt/x-agent /opt/x-agent/venv/bin/python3 -m x_agent.cli status
printf '%s' 'Final approved text' |
PYTHONPATH=/opt/x-agent /opt/x-agent/venv/bin/python3 -m x_agent.cli post --publish
printf '%s' 'Final approved text' |
PYTHONPATH=/opt/x-agent /opt/x-agent/venv/bin/python3 -m x_agent.cli post --publish --image /absolute/path/to/image.png
printf '%s' '["1/2 Root", "2/2 Reply"]' |
PYTHONPATH=/opt/x-agent /opt/x-agent/venv/bin/python3 -m x_agent.cli thread --publish --image /absolute/path/to/image.png
printf '%s' 'Final approved text' |
PYTHONPATH=/opt/x-agent /opt/x-agent/venv/bin/python3 -m x_agent.cli post --publish --community 'Hacking / Ethical Hacking'
printf '%s' 'Final approved reply' |
PYTHONPATH=/opt/x-agent /opt/x-agent/venv/bin/python3 -m x_agent.cli reply https://x.com/account/status/123 --publish
```
## MCP tools
| Tool | Side effect | Description |
| --- | --- | --- |
| x_status() | No | Check authenticated X session. |
| list_x_communities() | No | List Communities available to this account. |
| create_x_post(text, community=None, image_path=None) | Yes | Publish one approved post. community=None means Everyone. |
| create_x_thread(posts, community=None, image_path=None) | Yes | Publish a linear reply thread; image applies to root only. |
| reply_x_post(post_url, text) | Yes | Reply to an existing post. |
## HTTP MCP
The Streamable HTTP endpoint uses a bearer token and listens on 127.0.0.1:8765 by default.
Create /etc/x-agent/mcp.env with root-only permissions:
```bash
X_AGENT_MCP_TOKEN=replace-with-a-long-random-value
X_AGENT_X_USERNAME=your_x_handle
```
Install systemd/x-agent-mcp.service as /etc/systemd/system/x-agent-mcp.service, then:
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now x-agent-mcp.service
sudo systemctl status x-agent-mcp.service
```
If reverse-proxying externally, use TLS, bearer authentication, restrictive firewall or proxy policy, and keep cookies and logs inaccessible.
## Community publishing
Omitting community preserves X's default audience: Everyone.
With community="Exact Community Name", the agent opens the audience picker before entering text, finds a single exact normalized match, selects it, and verifies the result. Any ambiguity aborts before root publication. Thread replies follow the context created by the root post.
Use list_x_communities() before publishing when the display name is uncertain.
## Image publishing
Pass an absolute local path through image_path (MCP) or --image (CLI). Supported formats are JPG, JPEG, PNG, WEBP, and GIF. A thread can have an image on the root post.
Before posting, the agent requires:
1. An attachment preview rendered by X in the active composer.
2. A successful media-upload response.
If either proof is missing, publication aborts without creating a post.
## Diagnostics
Runtime log:
```text
/var/log/x-agent/thread-debug.log
```
Failure screenshots are stored under /var/log/x-agent/. Diagnostics omit post bodies, cookie values, bearer tokens, and full upload URLs. They retain operation stage, selector decision, audience state, response status, post IDs, and post URLs.
## Testing
```bash
PYTHONPATH=. ./venv/bin/python3 tests/test_posts.py
./venv/bin/python3 -m py_compile x_agent/*.py
```
## Deployment notes
Keep reviewed source in a Git repository, for example /home/ai/x-agent-build, and deploy a reviewed copy to /opt/x-agent. Restart x-agent-mcp.service after changing long-running MCP code; CLI executions load fresh code every run.
## License
Licensed under the [MIT License](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues