Post X MCP
Servidor MCP para postar no X (Twitter) com suporte a múltiplas contas
Documentação
mcp-server-x
Um servidor MCP (Model Context Protocol) para X (Twitter). Construído em Rust usando OAuth 1.0a e a API X v2. Suporta múltiplas contas.
Comunica via stdio usando JSON-RPC 2.0.
Ferramentas
| Ferramenta | Descrição |
|---|---|
list_accounts | Lista as contas disponíveis e qual é a padrão |
post_tweet | Publica um tweet com mídia opcional (até 4 imagens, 1 vídeo ou 1 GIF) |
post_thread | Publica um thread de até 25 tweets, cada um com mídia opcional |
delete_tweet | Exclui um tweet por ID ou URL |
upload_media | Envia mídia para anexo posterior (retorna um media_id) |
update_profile | Atualiza sua bio/descrição, nome de exibição, localização e/ou URL do site (endpoint legado v1.1) |
update_profile_banner | Atualiza a imagem de cabeçalho/banner do perfil (endpoint legado v1.1) |
search_tweets | Pesquisa tweets recentes (últimos 7 dias) com operadores do Twitter |
get_timeline | Obtém sua linha do tempo inicial em ordem cronológica reversa |
get_bookmarks | Obtém seus tweets com marcadores (paginado) |
get_me | Obtém o perfil do usuário autenticado |
lookup_user | Consulta qualquer usuário por @username ou ID numérico |
get_followers | Lista seus seguidores (paginado) |
get_following | Lista quem você segue (paginado) |
get_all_followers | Busca TODOS os seus seguidores em uma única chamada (paginação automática) |
get_all_following | Busca TODAS as contas que você segue em uma única chamada (paginação automática) |
like_tweet | Curte um tweet por ID ou URL |
unlike_tweet | Descurte um tweet por ID ou URL |
retweet | Retweeta um tweet por ID ou URL |
unretweet | Desfaz um retweet por ID ou URL |
bookmark_tweet | Adiciona um tweet aos marcadores por ID ou URL |
unbookmark_tweet | Remove um marcador por ID ou URL |
get_trends | Obtém os assuntos em alta atuais para uma localização WOEID (padrão: mundial) |
get_dm_events | Obtém mensagens diretas recentes em todas as conversas |
send_dm | Envia uma mensagem direta para uma conversa |
follow_user | Segue um usuário por username ou ID |
unfollow_user | Deixa de seguir um usuário por username ou ID |
Todas as ferramentas aceitam um parâmetro opcional account para selecionar qual conta X usar. Omita-o para usar a conta padrão.
Início Rápido
1. Compilar
cargo build --release
Produz target/release/mcp-server-x (otimizado com LTO, reduzido).
2. Configurar credenciais
O servidor procura a configuração no primeiro local existente entre:
$XDG_CONFIG_HOME/mcp-server-x/config.toml~/.config/mcp-server-x/config.toml$XDG_CONFIG_HOME/mcp-server-post-x/config.toml(legado)~/.config/mcp-server-post-x/config.toml(legado)
Você também pode executar sem nenhum arquivo de configuração fornecendo credenciais por meio de variáveis de ambiente (ótimo para contêineres/CI):
export X_API_KEY=...
export X_API_KEY_SECRET=...
export X_ACCESS_TOKEN=...
export X_ACCESS_TOKEN_SECRET=...
# Optional:
# export X_ACCOUNT_NAME=myaccount
POST_X_* / POST_X_ACCOUNT_NAME ainda são aceitos se as variáveis X_* não estiverem definidas.
Crie o arquivo de configuração (abordagem clássica):
mkdir -p ~/.config/mcp-server-x
Crie ~/.config/mcp-server-x/config.toml:
Conta única (sem default_account necessário):
[accounts.myaccount]
api_key = "your-api-key"
api_key_secret = "your-api-key-secret"
access_token = "your-access-token"
access_token_secret = "your-access-token-secret"
Múltiplas contas:
default_account = "myaccount"
[accounts.myaccount]
api_key = "your-api-key"
api_key_secret = "your-api-key-secret"
access_token = "your-access-token"
access_token_secret = "your-access-token-secret"
[accounts.otheraccount]
api_key = "your-api-key"
api_key_secret = "your-api-key-secret"
access_token = "other-access-token"
access_token_secret = "other-access-token-secret"
Observações:
- As chaves das contas são usernames do X (ex.:
[accounts.codechap]) - Se você tiver múltiplas contas,
default_accounté obrigatório - Se você tiver uma conta,
default_accounté opcional (detecção automática) - Múltiplas contas podem compartilhar o mesmo
api_key/api_key_secret(mesmo app X). Apenas oaccess_token/access_token_secretdifere por conta. bookmark_tweet/unbookmark_tweetexigem OAuth 2.0 User Context (bookmark.write). Adicioneoauth2_client_id,oauth2_client_secret,oauth2_access_tokeneoauth2_refresh_tokenopcionais na conta que precisa de marcadores. OAuth 1.0a permanece em uso para todas as outras ferramentas. Gere o token de usuário no Console de Desenvolvedor do X (App → Keys & Tokens → OAuth 2.0 Access Token) comtweet.read,users.read,bookmark.read,bookmark.writeeoffline.access. Os tokens de acesso duram cerca de 2 horas; o servidor os renova comoauth2_refresh_token(e grava os tokens rotacionados de volta emconfig.toml).
Proteja-o:
chmod 700 ~/.config/mcp-server-x
chmod 600 ~/.config/mcp-server-x/config.toml
Veja Obtendo credenciais abaixo para saber como obtê-las.
3. Adicionar ao seu cliente MCP
Claude Code (~/.claude.json):
{
"mcpServers": {
"x": {
"command": "/path/to/mcp-server-x"
}
}
}
Depois, peça coisas como:
- "Publique um tweet dizendo olá mundo"
- "Publique um tweet como securechap dizendo olá mundo"
- "Pesquise tweets sobre Rust"
- "Mostre minha linha do tempo"
- "Curta este tweet: https://x.com/someone/status/123456"
- "Quem são meus seguidores?"
- "Consulte @elonmusk"
- "Liste minhas contas"
Referência de Ferramentas
list_accounts
Sem parâmetros obrigatórios. Retorna os nomes das contas disponíveis, qual é a padrão e usernames em cache.
post_tweet
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
text | string | sim | Texto do tweet (máx. 280 caracteres) |
media | array | não | Mídia para enviar e anexar. Cada item: { path, alt_text? }. Máx. 4 imagens, ou 1 vídeo, ou 1 GIF. |
media_ids | array | não | IDs de mídia pré-enviados para anexar (máx. 4). Mutuamente exclusivo com media. |
reply_to | string | não | ID do tweet para responder |
post_thread
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
tweets | array | sim | Array de tweets (máx. 25). Cada um: { text, media? } |
delete_tweet / like_tweet / unlike_tweet / retweet / unretweet / bookmark_tweet / unbookmark_tweet
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
tweet_id | string | sim | ID do tweet ou URL completa do tweet |
Todos aceitam URLs como https://x.com/user/status/123456 — o ID é extraído automaticamente.
upload_media
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
path | string | sim | Caminho do arquivo local. Suportados: jpeg/png/webp (máx. 5MB), gif (máx. 15MB), mp4 (máx. 512MB) |
alt_text | string | não | Texto alternativo (apenas imagens e GIFs, não vídeo) |
Retorna um media_id para usar com o parâmetro media_ids de post_tweet.
update_profile
Atualiza os campos de texto do perfil do usuário autenticado. Pelo menos um campo deve ser fornecido; apenas os campos passados são alterados, e passar uma string vazia limpa esse campo.
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
description | string | não* | Nova bio/descrição (máx. 160 caracteres; string vazia limpa) |
name | string | não* | Novo nome de exibição (1-50 caracteres) |
location | string | não* | Nova localização (máx. 30 caracteres; string vazia limpa) |
url | string | não* | Nova URL do site exibida no perfil (máx. 100 caracteres; string vazia limpa) |
* Pelo menos um de description, name, location ou url é obrigatório.
Usa o endpoint legado POST /1.1/account/update_profile.json (sem equivalente v2). Exige que o app tenha permissão Read and Write; sem ela, o endpoint retorna 403.
update_profile_banner
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
path | string | sim | Caminho do arquivo local da imagem do banner (apenas JPEG/PNG/WebP, máx. 5MB). O X recomenda 1500x500 pixels. |
width | inteiro | não | Largura da imagem (para recorte) |
height | inteiro | não | Altura da imagem (para recorte) |
offset_left | inteiro | não | Deslocamento esquerdo (pixels) para início do recorte |
offset_top | inteiro | não | Deslocamento superior (pixels) para início do recorte |
Usa o endpoint legado POST /1.1/account/update_profile_banner.json (parâmetro banner em base64; sem equivalente v2). Sucesso retorna HTTP 200 sem corpo.
search_tweets
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
query | string | sim | Consulta de pesquisa. Suporta: from:user, #hashtag, @mention, "exact phrase", -exclude, lang:en |
max_results | inteiro | não | 10-100 (padrão 10) |
sort_order | string | não | recency ou relevancy |
pagination_token | string | não | Token da próxima página da resposta anterior |
get_trends
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão; determina qual limite de taxa do app é usado) |
woeid | inteiro | não | WOEID da localização (padrão: 1 = Mundial). Veja valores comuns na descrição da ferramenta. |
Retorna nomes dos assuntos em alta e volumes aproximados de postagens.
get_timeline
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
max_results | inteiro | não | 1-100 (padrão 20) |
exclude | string | não | replies, retweets ou ambos separados por vírgula |
pagination_token | string | não | Token da próxima página |
get_bookmarks
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
max_results | inteiro | não | 1-100 (padrão 20) |
pagination_token | string | não | Token da próxima página |
lookup_user / follow_user / unfollow_user
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
user | string | sim | Username (com ou sem @) ou ID numérico do usuário |
get_followers / get_following
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
max_results | inteiro | não | 1-100 (padrão 20) |
pagination_token | string | não | Token da próxima página |
get_all_followers / get_all_following
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
max_users | inteiro | não | Limite de segurança (padrão 5000, máx. 10000). Evita respostas enormes para contas com muitos seguidores. |
Pagina automaticamente pelos resultados (100 por página) com atraso de 200ms entre páginas. Para contas com dezenas de milhares de seguidores, prefira as ferramentas paginadas get_followers / get_following.
get_dm_events
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
max_results | inteiro | não | 1-100 (padrão 20) |
pagination_token | string | não | Token da próxima página |
send_dm
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
conversation_id | string | sim | ID da conversa de DM (obter de get_dm_events) |
text | string | sim | Texto da mensagem |
get_me
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
account | string | não | Conta a usar (omitir para a padrão) |
Retorna seu ID de usuário, nome de exibição e @username.
Adicionando Contas Adicionais
Para adicionar outra conta X a um app existente (sem uma conta de desenvolvedor separada), use o script de autorização OAuth incluído:
export X_API_KEY="your-app-api-key"
export X_API_KEY_SECRET="your-app-api-key-secret"
./oauth-authorize.sh
Importante: O script não contém mais nenhuma credencial codificada. Você deve fornecer as Consumer Keys do seu próprio app por meio das duas variáveis de ambiente mostradas acima. Este fluxo executa o fluxo OAuth 1.0a baseado em PIN de 3 etapas:
- Abre uma URL onde a nova conta autoriza seu aplicativo
- Você cola o PIN de volta no terminal
- Ele gera o bloco de configuração
[accounts.username]para adicionar ao seuconfig.toml
Todas as contas que você autoriza compartilham o mesmo App X (e seus limites de taxa + cobrança). Este é o padrão normal para uso com múltiplas contas.
Obtendo Credenciais
- Acesse developer.x.com e cadastre-se para uma conta de desenvolvedor
- Crie um Projeto e um App no Console do Desenvolvedor
- Nas configurações do seu App, configure a Autenticação de usuário:
- Permissões do app: Leitura e escrita (e Mensagens diretas se você quiser suporte a DM)
- Tipo: Web App, App Automatizado ou Bot
- URL de callback:
https://example.com(não usada, mas obrigatória) - URL do site: qualquer URL válida
- Vá para Chaves e tokens e gere:
- API Key e API Key Secret (em Consumer Keys)
- Access Token e Access Token Secret (em Authentication Tokens)
- Copie todos os quatro valores para o seu
config.tomlem[accounts.yourusername]
O servidor valida as credenciais na inicialização. Se você receber erros 401 persistentes, regenere seus tokens em developer.x.com.
Desenvolvimento
cargo build # debug build
cargo run # run in dev mode
RUST_LOG=debug cargo run # debug logging (credentials are redacted)
cargo test # run unit tests
cargo clippy -- -D warnings # strict lint check (must pass)
cargo build --release # optimized binary
Detalhes Técnicos
- Autenticação: OAuth 1.0a com assinaturas HMAC-SHA1 (RFC 5849, codificação percentual RFC 3986)
- Multi-contas: Várias contas X por instância do servidor, selecionáveis por chamada de ferramenta
- API de Tweets: X API v2 (
api.x.com/2/) - Upload de mídia: upload em partes v1.1 (
upload.twitter.com/1.1/media/upload.json) — fluxo INIT/APPEND/FINALIZE/STATUS para vídeo/GIF, multipart simples para imagens - Limites de mídia: JPEG/PNG/WebP até 5MB, GIF até 15MB, MP4 até 512MB
- Validação de mídia: Máximo de 4 imagens OU 1 vídeo OU 1 GIF por tweet (sem mistura)
- Postagem em thread: atraso de 500ms entre tweets, encadeados via
in_reply_to_tweet_id - Lógica de repetição: repetição automática com backoff exponencial em erros 503
- Limites de taxa: respostas 429 incluem timestamp de redefinição na mensagem de erro (sem repetição automática — quem chama decide)
- Segurança:
get_all_followers/get_all_followingsão limitados a 10 mil usuários por padrão para evitar destruir janelas de contexto de LLM - Edição Rust: 2021 (ampla compatibilidade)
Estrutura do Projeto
src/
main.rs — entry point, config loading, tracing, stdio transport
server.rs — MCP tool handlers, response formatting, multi-account routing
api.rs — X API client: OAuth signing, tweet/media/user/DM endpoints
params.rs — tool parameter types (serde + JSON Schema)