@xtweetly/mcp
v0.3.0
Published
Full-power MCP server for xtweetly — read, write, and monitor your X account from any MCP-compatible client.
Readme
@xtweetly/mcp
Full-power MCP server for xtweetly. Read, write, and monitor your X (Twitter) account from any MCP-compatible client — Claude Desktop, MiniMax, Cursor, or your own agent. Talks to xtweetly over HTTPS, so your X session cookies never leave the xtweetly API.
The server is published to npm as a standalone package. No private xtweetly code is bundled — the package only contains the MCP layer and the public-API HTTP client.
Install + run
The MCP server is launched by your MCP client (Claude Desktop / MiniMax / etc.). Configure it
under mcpServers:
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"xtweetly": {
"command": "npx",
"args": ["-y", "@xtweetly/mcp"],
"env": {
"XTWEETLY_API_KEY": "xwtk_…",
"XTWEETLY_API_BASE_URL": "https://api.xtweetly.com"
}
}
}
}Local dev (against a local xtweetly API)
{
"mcpServers": {
"xtweetly": {
"command": "node",
"args": ["/absolute/path/to/xtweetly/packages/mcp/dist/index.js"],
"env": {
"XTWEETLY_API_KEY": "xwtk_…",
"XTWEETLY_API_BASE_URL": "http://localhost:3000"
}
}
}
}Or run it directly:
XTWEETLY_API_KEY=xwtk_… XTWEETLY_API_BASE_URL=http://localhost:3000 npx @xtweetly/mcpGetting an API key
- Open the xtweetly dashboard and connect your X account (Settings → Connect X).
- Go to Settings → API keys and create a new key. The key is scoped to one workspace.
- Paste the key into
XTWEETLY_API_KEY. Keep it secret — anyone with the key can post, like, follow, and delete on the workspace's X account.
Tools
Read
| Tool | Description |
| --- | --- |
| search_tweets | Search recent tweets matching a query. |
| get_user | Look up an X user by handle. |
| get_user_tweets | Get a user's recent authored tweets. |
| get_account_signals | Read bookmarks, likes, or following from the connected account. |
Write
All write tools act on the connected X account (not arbitrary users).
| Tool | Description |
| --- | --- |
| post_tweet | Publish a new tweet. |
| reply_to_tweet | Post a reply to a tweet. |
| like_tweet / unlike_tweet | Like / unlike a tweet. |
| retweet / unretweet | Retweet / undo a retweet. |
| follow_user / unfollow_user | Follow / unfollow a user. |
| delete_tweet | Delete a tweet authored by the connected account. |
Monitors
| Tool | Description |
| --- | --- |
| list_monitors | List every monitor on this workspace. |
| get_monitor | Get one monitor with its recent state. |
| create_keyword_monitor | Create a keyword monitor (X search syntax). |
| create_timeline_monitor | Create a monitor for a specific user's timeline. |
| pause_monitor / resume_monitor / delete_monitor | Lifecycle. |
| get_monitor_events | Paged history of events. |
Analyze
| Tool | Description |
| --- | --- |
| analyze_profile | Full profile analysis with engagement / timing / format breakdown. |
| score_draft | Score a draft tweet against X's algorithm signals. |
Resources (live, subscribable)
The MCP server also exposes resources the agent can subscribe to for live data
push (2025-era per-resource updates). The capability advertises
resources: { subscribe: true, listChanged: true }.
| URI | What it is |
| --- | --- |
| xtweetly://monitors | Current list of monitors owned by the workspace. |
| xtweetly://monitors/{id}/events | Recent events for a single monitor (poll-bridged from /v0/monitors/:id/history). |
The polling bridge fetches fresh data every 15s (override with
XTWEETLY_RESOURCE_POLL_MS or the resourcePollMs buildServer option) and
emits notifications/resources/updated only when the payload changes
(stable-stringify diff). The timer starts on first subscribe, stops on last
unsubscribe — no idle polling.
Example client flow:
const { resources } = await client.listResources();
for (const r of resources) {
if (r.uri === "xtweetly://monitors") await client.subscribeResource({ uri: r.uri });
}
client.setNotificationHandler(ResourceUpdatedNotificationSchema, (n) => {
console.log("updated:", n.params.uri);
return client.readResource({ uri: n.params.uri });
});Safety notes
- Every write tool runs on your own X account, on the workspace's BYO session. There is
no admin / global flag — if your workspace has automation disabled, writes still work (MCP
is treated like manual user activity). The dashboard's
automationEnabledflag controls background automation only. - All calls are rate-limited and budgeted server-side under the "interactive" traffic class so MCP activity never starves your long-lived monitors.
- The API key is a bearer token. Anyone with it can act on your X account. Treat it like a password — store in a secret manager, never commit it, rotate from the dashboard if it leaks.
Safety modes
XTWEETLY_CONFIRM_DESTRUCTIVE (default off) — opt-in human-on-the-loop guard for the
four destructive tools: delete_tweet, unlike_tweet, unretweet, unfollow_user.
When the flag is on:
XTWEETLY_CONFIRM_DESTRUCTIVE=true XTWEETLY_API_KEY=... node packages/mcp/dist/index.js…a destructive call without confirm: true returns instead of executing:
{
"requires_explicit_confirm": true,
"hint": "Destructive action blocked: delete this tweet. Pass confirm: true in the same call to proceed. Set XTWEETLY_CONFIRM_DESTRUCTIVE=false on the server (or unset it) to disable this guard."
}The agent must re-issue the same call with confirm: true to actually run it. Non-destructive
tools (post_tweet, reply_to_tweet, like_tweet, retweet, follow_user) ignore the flag
and run normally.
When the flag is off (default), the confirm field is present in the schema but ignored —
back-compat with v0.1.0 callers.
Development
pnpm install
pnpm --filter @xtweetly/mcp dev # stdio server with tsx watch
pnpm --filter @xtweetly/mcp test # node --test (no external deps)
pnpm --filter @xtweetly/mcp build # tsc → dist/
pnpm --filter @xtweetly/mcp mock # standalone stub of /v0/* on :7777Testing locally
Two paths. Pick by what you need to validate.
A. Mock API + MCP Inspector (no infra, no X account)
# Terminal 1
pnpm --filter @xtweetly/mcp mock # listens on http://127.0.0.1:7777
# Terminal 2
npx -y @modelcontextprotocol/inspector \
--config '{"mcpServers":{"xtweetly":{"command":"node","args":["/abs/path/packages/mcp/dist/index.js"],"env":{"XTWEETLY_API_KEY":"xwtk_test","XTWEETLY_API_BASE_URL":"http://127.0.0.1:7777"}}}}'Open the Inspector URL it prints. You'll see all 23 tools, can click any, fill arguments, and see JSON responses. The mock returns plausible fixtures, so you can exercise the full tool surface without an X session.
B. Against a real xtweetly API (full validation)
# Start the API + worker locally
pnpm dev
# 1. Open http://localhost:3001 and connect an X account.
# 2. Settings → API keys → create a key (xwtk_…).
# 3. Configure your MCP client with that key and http://localhost:3000:{
"mcpServers": {
"xtweetly": {
"command": "node",
"args": ["/abs/path/packages/mcp/dist/index.js"],
"env": {
"XTWEETLY_API_KEY": "xwtk_…",
"XTWEETLY_API_BASE_URL": "http://localhost:3000"
}
}
}
}Writes go to your real X account. Start with reads (get_user, search_tweets,
get_account_signals) before touching post_tweet or like_tweet.
C. Programmatic smoke (no client UI)
# Build + run the mock + drive the MCP server over stdio
pnpm --filter @xtweetly/mcp build
node packages/mcp/test/mock-api.mjs & # mock on :7777
sleep 0.3
# Then point any MCP client at the built server with XTWEETLY_API_BASE_URL=http://127.0.0.1:7777The Inspector (path A) is the fastest way to validate behavior visually before connecting it to MiniMax / Claude Desktop.
Publishing
Tag-triggered (preferred)
Push a semver tag from the feat/xtweetly-mcp-server branch (or main):
git checkout main
git pull
git merge --no-ff feat/xtweetly-mcp-server -m "release: @xtweetly/mcp 0.1.0"
pnpm --filter @xtweetly/mcp version 0.1.0 # bumps version + commits a tag-less version bump
git tag v0.1.0
git push origin main v0.1.0.github/workflows/publish-mcp.yml runs:
- install + typecheck + lint + test + build
- pack dry-run + leak audit (refuses to publish if a private
@xtweetly/*import slipped into the package source) pnpm publish --no-git-checks --access public
Required secret: NPM_TOKEN (npm Automation token, scoped to @xtweetly/*).
Manual (emergency)
NPM_TOKEN=npm_… pnpm --filter @xtweetly/mcp publish --no-git-checksThe package.json files whitelist ships only dist/, README.md, and LICENSE. CI runs
pnpm pack --dry-run to ensure no private xtweetly code (@xtweetly/core,
@xtweetly/storage, etc.) leaks into the tarball.
License
MIT. See LICENSE.
