mcpField
X
X (Twitter)

X (Twitter)

ローカル
github.comソーシャルメディア27 週間前に更新

X (Twitter) について

mcp-xは、X API v2を通じてXアカウントの読み取り、検索、管理を行うGo製MCPサーバーです。42種類のツールがあり、OAuth 1.0aのユーザーコンテキストで、認証情報に対応するアカウントとして操作します。

主な機能

  1. 01最近の投稿の検索と集計
  2. 02タイムライン、メンション、ブックマークの読み取り
  3. 03ユーザーとリストの管理
  4. 04投稿、いいね、リポスト
  5. 05メディアのアップロードと添付

活用シーン

  1. 01複数のクエリで最近の投稿を検索
  2. 02アカウントのタイムラインとブックマークを確認
  3. 03アカウントとして投稿やリアクションを実行

MCP 対応

MCP対応クライアントにX API v2の42種類のツールを提供します。stdioとストリーミングHTTPのトランスポートに対応しています。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ
パッケージ
ocighcr.io/role1776/mcp-x:0.1.1
mcpbmcp-x_0.1.1_darwin_amd64.mcpb0.1.1
mcpbmcp-x_0.1.1_darwin_arm64.mcpb0.1.1
mcpbmcp-x_0.1.1_linux_amd64.mcpb0.1.1
mcpbmcp-x_0.1.1_linux_arm64.mcpb0.1.1
mcpbmcp-x_0.1.1_windows_amd64.mcpb0.1.1
mcpbmcp-x_0.1.1_windows_arm64.mcpb0.1.1

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

mcp-x

LLM に X(Twitter)API を提供する MCP サーバーです。投稿の読み取りや検索、ユーザーやリストの管理、メディアのアップロード、投稿の公開を行えます。実行時に使用するキーに紐づくアカウントとして操作します。

ライセンス MIT Go MCP トランスポート X API v2 OAuth 1.0a 有料 API

ウェブサイト · 料金 · 認証情報 · ツール · クイックスタート · 設定 · アーキテクチャ · コントリビューション


概要

mcp-x は、Go で記述された Model Context Protocol サーバーです。X API v2 を、MCP 互換クライアント(Claude Desktop、IDE エージェント、カスタム LLM アプリ)に、投稿、ユーザー、リスト、メディアを扱う 42 個のツールとして提供します。

OAuth 1.0a ユーザーコンテキストで認証するため、すべての呼び出しは 実際の X アカウント、つまり 4 つのキーが属するアカウントとして実行されます。x_post_create は公開投稿を行います。x_user_follow は実際にフォローします。x_post_delete は取り消せません。これはサンドボックスではなく、無料でもありません。エージェントに接続する前に、X API は有料ですをご確認ください。

MCP SDK がサポートする両方のトランスポートを利用でき、どちらも同じツールセットを提供します。

  • stdio — クライアントがバイナリを起動し、stdin/stdout 経由で通信します(デフォルト。デスクトップクライアントに最適です)。
  • http — 長時間稼働するストリーミング HTTP サーバーです(リモート環境や共有環境へのデプロイに便利です)。

X API の利用には料金がかかります

警告

無料プランはもうありません。 X は新規開発者向けの Free/Basic/Pro サブスクリプションプランを廃止し、従量課金制クレジットに移行しました。Developer Console で事前にクレジットを購入し、リクエストごとに残高からリアルタイムで差し引かれます。従来の Basic(月額 $200)と Pro(月額 $5,000)は、すでに契約していたアカウントでのみ引き続き利用できます。Enterprise は月額約 $42,000 からです。現在、新しく開発者アカウントを作成すると、従量課金制のみが適用されます。

執筆時点の料金です(公式料金 — 2026 年に何度か変更されているため、必ず Console で再確認してください)。

操作料金
投稿の読み取り返された投稿 1 件あたり $0.005
自分のリソースの読み取り(自分の投稿、ブックマーク、フォロワー、「いいね」、リスト)リソース 1 件あたり $0.001
ユーザーの読み取り返されたユーザー 1 人あたり $0.010
「いいね」/ミュート/ブロックの読み取りリソース 1 件あたり $0.001
フォロワー/フォロー中のアカウントの読み取りリソース 1 件あたり $0.010
投稿の公開リクエスト 1 回あたり $0.015
URL を含む投稿の公開リクエスト 1 回あたり $0.200
「いいね」/リポストなどのインタラクションリクエスト 1 回あたり $0.015
リストとブックマークへの書き込みリクエスト 1 回あたり $0.005~$0.010

このことから、次の 2 点が導かれます。どちらもサーバーに組み込まれています。

  • 読み取りの料金は、リクエストごとではなく、返された リソースごと に発生します。 同じクエリで x_posts_search の max_results: 100 を指定すると、max_results: 5 を指定した場合の 20 倍の料金がかかります。すべての読み取りツールの説明では、質問に答えるのに必要な最小の max_results を指定するようモデルに指示しています。また、バッチ処理ツール(x_posts_lookup、x_users_lookup)では、繰り返し処理するのではなく、まとめて処理するよう指示しています。
  • x_posts_count は投稿読み取りの予算を消費しません。 同じクエリ構文で、分/時間/日ごとに分類した一致件数を返します。まず x_posts_count でトピックの規模を把握してから、x_posts_search の料金を支払ってください。

X は重複排除も行います。UTC の 24 時間以内に同じリソースを 2 回取得しても、料金が発生するのは 1 回です。また、従量課金制では、請求サイクルあたりの投稿読み取り数が 300 万件に制限されています。それを超えた場合は、Enterprise のみ利用できます。

料金を使い切ると、API は専用のエラーを返します。サーバーはそれを、モデルに再試行しないよう明示するメッセージに変換します。詳しくはエラーを参照してください。


認証情報

サーバーには、1 つの X アプリから取得した OAuth 1.0a の値が4 つ必要です。

X_API_KEY
X_API_KEY_SECRET
X_ACCESS_TOKEN
X_ACCESS_TOKEN_SECRET

最初のペアは アプリ を識別し、2 番目のペアはそのアプリを通じて操作する アカウント を識別します。mcp-x が AuthenMethodOAuth1UserContext を使用し、アプリ専用のベアラー認証を使用しないのは、すべての書き込みエンドポイントとすべての「自分」に関するエンドポイント(x_users_me、x_posts_home、x_bookmarks_list、メンション)でユーザーコンテキストが必要になるためです。ベアラートークンモードはありません。

認証情報の取得方法 — 誰もが間違える 1 つの手順
  1. developer.x.com に移動し、プロジェクトからアプリを開きます。
  2. User authentication settings を開き、App permissions を Read and Write に設定します。必ず最初に行ってください。
  3. その後でのみ、Keys and tokens に移動し、Access Token and Secret を生成します。

重要

アクセストークンには、生成時点でアプリに設定されていた権限が固定されます。 アプリが Read-only のときにトークンを作成し、その後アプリの権限を Read and Write に変更しても、トークンは 読み取り専用のまま です。アプリ設定ページを見ても、このことはわかりません。Keys and tokens に戻って Access Token and Secret を再生成するまで、すべての書き込みは X の oauth1-permissions 問題タイプで失敗し続けます。

これは X API で最もよくある設定ミスです。そのため、サーバーは起動時にチェックし、次のメッセージを表示して起動を拒否します。

the access token is read-only: set the app permissions to Read and Write
in the X Developer Console, then regenerate the Access Token and Secret

API Key/Secret の再生成では解決しません。Access Token and Secret を再生成してください。

起動時の検証

ツールを1つでも登録する前に、サーバーは15秒の期限内にGET /2/users/meを1回呼び出します(client.Bootstrap)。これには3つの役割があります。

  • 4つのキーが有効であることを確認します。不正なキーがある場合は、最初のツール呼び出しではなくプロセスが失敗します。
  • 上記の読み取り専用トークンの落とし穴を検出します。
  • キー所有者の数値のユーザーIDをキャッシュします。すべての書き込みエンドポイントはPOST /2/users/:id/...であり、書き込みのたびにIDを調べると、別途課金対象のリクエストが必要になるためです。

ここでの失敗は、意図的に致命的なものとして扱われます。起動した後ですべての呼び出しに失敗するサーバーより、起動しないサーバーのほうがましです。

この選択に伴うコストは、はっきり述べておく必要があります。**資金があるX開発者アカウントがなければ、このサーバーを試す方法はありません。**認証情報がなければ起動できず、ツール一覧も表示されません。/mcpとclaude mcp listには、接続失敗とだけ表示されます。それ以外の方法でインストールを確認するには、バイナリを-version付きで実行し、公開されるツールについてはツールのセクションを確認してください。

キーは秘密情報です

4つの値は、書き込みアクセス権を持つ有効なアカウントの認証情報です。自分だけが読み取れるファイルに保管し、-envで指定してください。また、決してコミットしないでください。.envはgitignoreの対象で、.env.exampleはテンプレートです。MCPクライアントで実行する場合は、クライアントのenvブロックも使用できます。この設定は.envファイルより優先されます。


ツール

4つのグループに42個のツールがあります。各ツールにはMCPアノテーションが付いています。読み取り操作にはreadOnlyHint、取り消せない操作(x_post_delete、x_list_delete、いいねの取り消し、リポストの取り消し、フォロー解除、メンバーの削除)にはdestructiveHintが付いています。各ツールは出力スキーマに一致する構造化JSONペイロードを返します。SDKは同じJSONをテキストコンテンツブロックにも反映するため、structuredContentを読み取らないクライアントでも利用できます。

すべてのツールでtimeout_msを任意に指定できます。値はグループごとの[MIN, MAX]の範囲に収まるよう調整されます(制限を参照)。

投稿 — 読み取り
ツール説明
x_posts_search複数のクエリについて、最近の投稿を並列で検索します。最近の投稿の検索対象は、さかのぼって7日間のみです。
x_posts_countクエリごとの一致件数を、分・時間・日単位で集計します。投稿の読み取り回数を消費しません。検索前にトピックの規模を把握するために使います。
x_posts_lookup1回の呼び出しで、IDを指定して最大100件の投稿を取得します。
x_posts_by_user複数のユーザー名について、最近の投稿を並列で取得します。
x_posts_mentionsキー所有者にメンションした投稿です。
x_posts_homeキー所有者のホームタイムラインです。
x_posts_quotes指定した投稿を引用している投稿です。
x_posts_likedキー所有者がいいねした投稿です。
x_bookmarks_listキー所有者のブックマークです。
x_post_liked_by指定した投稿にいいねしたユーザーです。
x_post_reposted_by指定した投稿をリポストしたユーザーです。
x_posts_search
パラメーター型デフォルト備考
queries[]string—**必須。**並列で実行します。上限はPOSTS_MAX_QUERIES(5)です。各クエリは512文字以下です。
max_resultsint10クエリごとの投稿数です。1~100件。1件ごとに課金されます。
sort_orderstring—recency(新しい順)またはrelevancy(関連度順)です。
daysint7さかのぼる日数です。1~7日。APIはこれ以上さかのぼれません。
include_retweetsboolfalsefalseの場合、サーバーはすべてのクエリに-is:retweetを追加します。
timeout_msint6415000呼び出し全体のタイムアウトです。[2000, 60000]の範囲に調整されます。

クエリ演算子はクエリ文字列内に記述します。

演算子意味
スペースAND
OR明示的なOR
-termNOT
( )グループ化
from:user / to:user投稿者/宛先で指定
@user / #tagメンション/ハッシュタグ
"exact phrase"完全一致するフレーズ
lang:en言語
is:retweet is:reply is:quote is:verified投稿の種類
has:media has:images has:videos has:links添付ファイル
url:example.comリンク先のドメイン
conversation_id:1231つのスレッド
x_posts_count
パラメーター型デフォルト備考
queries[]string—必須。 x_posts_search と同じ演算子を使用します。
granularitystringhourminute、hour、day のいずれかです。
daysint71..7。同じ期間です。
timeout_msint6415000[2000, 60000] の範囲に制限されます。
x_posts_lookup
パラメーター型デフォルト備考
ids[]string—必須。 投稿 ID を1..100個指定します。まとめて取得し、IDごとに呼び出さないでください。
x_posts_by_user
パラメーター型デフォルト備考
usernames[]string—必須。 @ は付けません。POSTS_MAX_USERNAMES(5)までに制限され、並列で取得されます。
max_resultsint10ユーザーごとの投稿数。1..100です。
exclude[]string—replies および/または retweets。
daysint71..7です。
timeout_msint6415000[2000, 60000] の範囲に制限されます。
タイムラインツール

x_posts_mentions、x_posts_home、x_posts_liked、x_bookmarks_list は、max_results(1..100)、pagination_token、timeout_ms という同じ形式です。x_posts_quotes、x_post_liked_by、x_post_reposted_by には、必須の id もあります。

ページネーションは明示的かつ手動で行います。レスポンスに next_token が含まれるため、次のページではそれを pagination_token として渡してください。サーバーが自動でページを取得することはありません。ページごとに課金されるため、取得するかどうかは呼び出し元が判断します。

投稿 — 書き込み
ツール注釈説明
x_post_create書き込み投稿を公開します。公開され、課金対象です($0.015、リンク付きの場合は$0.20)。
x_post_delete破壊的操作自分の投稿を削除します。元に戻せません。
x_post_like / x_post_unlike書き込み/破壊的操作いいねは公開されます。
x_post_repost / x_post_unrepost書き込み/破壊的操作リポストは公開されます。
x_post_create
パラメーター型備考
textstring280文字以下です。media_ids が設定されていない場合は必須です。
reply_to_idstringこの投稿に返信します。
quote_idstringこの投稿を引用します。
media_ids[]stringx_media_upload で取得した ID を1..4個指定します。
pollobjectoptions(2..4)と duration_minutes(5..10080)を指定します。media_ids と併用できません。
reply_settingsstringfollowing、mentionedUsers、subscribers、verified のいずれかです。

同じテキストを連続して2回公開しようとすると、重複投稿として X に拒否されます。サーバーはこれを一般的な失敗としてではなく、個別のメッセージとして返します。

ユーザー
ツール注釈説明
x_users_lookup読み取り1回の呼び出しでユーザー名を最大100個、または ID を最大100個取得できます。どちらか一方のみで、両方は指定できません。解決できなかった名前は not_found に返されます。
x_users_me読み取りキーに紐づくプロフィールです。
x_user_followers / x_user_following読み取り1ページずつ取得します。max_results は最大1000です。
x_user_follow / x_user_unfollow書き込み/破壊的操作公開されます。
x_user_mute / x_user_unmute書き込みミュートは相手に通知されません。相手は引き続きあなたを見ることができます。
x_users_muted / x_users_blocked読み取りキー所有者がミュートまたはブロックしているアカウントです。

ブロックとブロック解除の操作は、意図的に公開していません。ブロックリストの読み取りは可能です。

リスト
ツール注釈説明
x_list_create書き込み名前は 25 文字以内、説明は 100 文字以内です。非公開リストを閲覧できるのは所有者のみです。
x_list_update書き込み変更するフィールドのみ送信してください。
x_list_delete破壊的操作取り消しできません。リスト、メンバーシップ、フォロワーがすべて削除されます。
x_list_get読み取りメンバー数とフォロワー数を含む、1 つのリストです。
x_lists_owned読み取りユーザー名で指定したアカウントが所有するリスト、または省略した場合はキー所有者が所有するリストです。
x_list_posts読み取りリストのメンバーによる最近の投稿です。投稿ごとに課金されます。
x_list_members読み取りリスト内のアカウントをページネーションで取得します。
x_list_member_add / x_list_member_remove書き込み / 破壊的操作ユーザー名で指定します。
x_list_follow / x_list_unfollow書き込み / 破壊的操作公開リストのみです。
x_list_pin / x_list_unpin / x_lists_pinned書き込み / 書き込み / 読み取りキー所有者がピン留めしたリストです。
メディア
x_media_upload

チャンク化された INIT → APPEND → FINALIZE フローを使用して画像、GIF、または動画をアップロードし、x_post_create 用の media_id を返します。

パラメーター型備考
pathstringローカルファイルです。MEDIA_ROOT 内に置く必要があります。
base64stringパスの代わりにファイルの内容を指定します。mime が必要です。
mimestring例:image/jpeg、video/mp4。base64 と併せて指定する必要があります。
categorystring必須です。 tweet_image(≤ 5 MB)、tweet_gif(≤ 15 MB)、tweet_video(≤ 512 MB)。
timeout_msint64デフォルトは 120000 で、[5000, 600000] の範囲に制限されます。アップロードと X のトランスコードの両方を対象とします。

知っておくべきことが 2 つあります。

  • MEDIA_ROOT は厳格な境界です。 デフォルト値がない必須設定であり、シンボリックリンクも含め、解決先がその外部になるパスはサーバーが拒否します。この設定がないと、このツールを持つ LLM がホスト上のあらゆるファイルを読み取り、投稿できてしまいます。専用のディレクトリを選んでください。
  • 動画は X によって非同期でトランスコードされます。 サーバーは MEDIA_POLL_INTERVAL_MS ごとに FINALIZE のステータスをポーリングしますが、エンコードに時間がかかると status: "pending" が返ることがあります。media_id は有効ですが、まだ投稿には使用できません。少し待ってから x_post_create を再試行してください。media_id は一定時間後に期限切れとなり、単一の投稿に使用することを想定しています。
部分的な結果

ファンアウトツールである x_posts_search、x_posts_count、x_posts_by_user は、それぞれの入力を並列で実行し、クエリまたはユーザー名ごとに 1 つのエントリーを返します。各エントリーには独自の status が含まれるため、1 つの入力に問題があっても、正常に処理できた結果は失われません。x_posts_lookup も ID ごとに同様に処理し(not found は解決できた投稿と並んで表示されます)、x_users_lookup は解決できなかった名前を not_found にまとめます。

入力が処理開始前に拒否された場合、またはすべての項目で失敗した場合に限り、呼び出し全体が失敗します。

エラー

失敗は isError: true とプレーンテキストのメッセージを含むツールの結果として返され、JSON-RPC エラーとしては返されません。モデルはメッセージを読んで呼び出しを自分で修正できます。メッセージはログを読む人ではなくモデル向けに書かれているため、再試行してはならないものにはその旨が明記されています。

メッセージ意味
the access token is read-only: …regenerate the Access Token and Secret読み取り専用トークンの罠です。
the monthly usage cap for this project is reached; …do not retry使用上限に達しました。リセットされるまで何も機能しません。
the project has no X API credits left; …do not retryクレジットが枯渇しました。リセットされないため、コンソールで追加してください。
rate limit exceeded; the window resets in about 15 minutes間隔を空けてください。連続してリクエストを送らないでください。
X rejected the credentials; check the four keysキーが無効か、取り消されています。
not authorized for this resource保護対象、削除済み、または他のユーザーのものです。
X rejected this as a duplicate of a recent postテキストを変更してください。
user not found / post not found / list not found説明のとおりです。
X failed to process the uploaded media; re-encode the fileトランスコードに失敗しました。
media exceeds the size limit for its category5 MB / 15 MB / 512 MB です。
the path is outside the directory this server is allowed to readMEDIA_ROOT 違反です。
post text exceeds 280 characters—
a post needs text unless it carries media—
a poll needs 2 to 4 options and a duration between 5 and 10080 minutes—
a post carries at most 4 media items—
too many ids in one call; the limit is 100—
invalid username: 1 to 15 letters, digits or underscoresリクエストを消費する前に、ローカルで検証されます。
every query failed; the X API may be unreachableすべての項目が失敗しました。
the call timed out; retry with a larger timeout_ms or fewer inputs—
the X API is unavailable5xx または分類されていない上流障害です。

分類は adapter/x/apierr で行われ、意図的に防御的な設計になっています。X は Content-Type: application/problem+json でエラーを返しますが、基盤となる gotwi クライアントはこれを JSON として認識しません。そのため、問題の本文全体が型付きフィールドにデコードされず、そのままメッセージフィールドに入ります。そこでマッパーは、レスポンスに含まれる可能性のあるすべての情報源を連結し、その文字列から問題タイプ(oauth1-permissions、usage-capped、credits-depleted、rate-limit-exceeded、…)を照合します。一致するものがなければ、HTTP ステータスコードを使います。

既知の制限事項
  • 最近の検索のみです。 過去 7 日間に限られます。過去のアーカイブ検索は別の(Enterprise)製品であり、接続されていません。
  • ブロック機能は公開されていません。 x_users_blocked はリストを読み取りますが、ブロック/ブロック解除ツールはありません。
  • ストリーミングエンドポイントはありません。 フィルター付きストリームとサンプルストリームは実装されていません。
  • DM はありません。
  • 1 プロセスにつき 1 アカウントです。 キーはプロセス全体で共有され、キーの所有者は起動時に一度だけ特定されます。複数のアカウントに対応するには、複数のプロセスが必要です。
  • ページネーションは手動です。 ツールは next_token を返します。各ページに課金されるため、自動的にページをたどることはありません。

クイックスタート

インストール

用途に合うものを選んでください。どれを選んでも、同じサーバーを利用できます。

コンテナー(Go ツールチェーンは不要です):

docker pull ghcr.io/role1776/mcp-x:0.1.1     # or :latest to track the newest release

依存するものでは、明示的なバージョンを指定してください。:latest は安定版リリースのたびに更新され、リリースによってツールの動作が追加・変更される場合があります。server.json には、MCP Registry が告知するものと同じバージョンが指定されています。

ビルド済みバイナリ — お使いのプラットフォーム用のアーカイブを最新リリースからダウンロードして展開し、mcp-x を PATH に追加してください。

MCP Bundle — .mcpb ファイルをインストールできるクライアントの場合は、mcp-x_<version>_<os>_<arch>.mcpb を最新リリースからダウンロードし、クライアントで開いてください。バンドルにはコンパイル済みバイナリが含まれているため、Docker も Go も不要です。また、インストール時にクライアントが必須の 5 つの値を尋ねます。OS と CPU アーキテクチャの両方に一致するファイルを選んでください。バンドルにはネイティブバイナリが 1 つ含まれています。

メモ

v0.1.1 より前にビルドされたバンドルでは、設定項目が宣言されていなかったため、クライアントは認証情報を尋ねず、サーバーは起動するたびに終了していました。v0.1.1 以降を使用してください。

ソースから(Go 1.26 以降が必要です):

git clone https://github.com/Role1776/mcp-x
cd mcp-x
make build          # -> bin/mcp-x

go install も使えますが、実行する前に知っておくべき注意点が 1 つあります。

go install github.com/Role1776/mcp-x/app/cmd/mcp-x@latest

Go モジュールは app/ にあるため、リリースタグ(v0.1.0)ではモジュールを指定できません。@v0.1.0 はそのまま失敗し、@latest は main 上の最新コミットの疑似バージョンに解決されます。また、go install でビルドした場合、バージョンは dev と報告されます。バージョンはモジュールではなく、リリースパイプラインで設定されるためです。リリースと完全に一致するビルドを使うには、ビルド済みバイナリ、コンテナー、またはチェックアウトしたタグからの make build を使用してください。

設定

クローンしたリポジトリ、または展開したリリースアーカイブ(どちらにもテンプレートが含まれています)から:

cp .env.example .env
$EDITOR .env        # fill in the four X_* keys and MEDIA_ROOT

コンテナーまたは .mcpb バンドルからインストールすると、コピー元のチェックアウトがありません。テンプレートは.env.exampleから取得するか、ファイルを使わずに、クライアントの env ブロック(以下を参照)に 5 つの値を渡してください。

5 つの値が必須で、それ以外はすべてデフォルト値があります。MEDIA_ROOT には、すでに存在するディレクトリの絶対パスを指定してください。サーバーは起動時にこれを確認し、指定が正しくない場合は、最初のアップロード時に失敗するのではなく、起動を拒否します。

実行
./bin/mcp-x -env /absolute/path/to/.env
フラグ説明
-versionバイナリが MCP クライアントに報告するバージョンを表示して終了します。ハンドシェイクとは異なり、認証情報がなくても応答できます。
-env.env ファイルへのパスです。暗黙的な検索は行われません — stdio では作業ディレクトリが MCP クライアントによって決定されるため、相対パスのデフォルト値は予測できません。このフラグを省略した場合、またはファイルが存在しない場合、サーバーは環境変数にフォールバックし、その旨を stderr に出力します。起動には、必須の 5 つの値をどこかで設定しておく必要があります。設定されていない場合、起動に失敗します。

起動に成功すると、認証済みアカウントがログに出力されます。

INFO authenticated with the X API op=app.Run user_id=1234567890
INFO MCP server has started op=app.Run transport=stdio
MCP クライアントへの接続(stdio)

Claude Code — 認証情報をインラインで指定して 1 つのコマンドで実行します(-- はサーバー自身のコマンドと、その前に指定するフラグを区切ります)。

claude mcp add mcp-x \
  -e X_API_KEY=... \
  -e X_API_KEY_SECRET=... \
  -e X_ACCESS_TOKEN=... \
  -e X_ACCESS_TOKEN_SECRET=... \
  -e MEDIA_ROOT=/absolute/path/to/media \
  -- /absolute/path/to/mcp-x

代わりに .env ファイルを指定することもできます:-- /absolute/path/to/mcp-x -env /absolute/path/to/.env。claude mcp list、またはセッション内で /mcp を実行して結果を確認してください。

Claude Desktop などの JSON 設定を使用するクライアント — ビルド済みバイナリを指定します。

{
  "mcpServers": {
    "x": {
      "command": "/absolute/path/to/mcp-x",
      "args": ["-env", "/absolute/path/to/.env"]
    }
  }
}

ファイルを使わずに、認証情報を env ブロックで渡すこともできます。環境変数は .env ファイルより優先されるため、クライアントの env ブロックの値が常に適用されます。

{
  "mcpServers": {
    "x": {
      "command": "/absolute/path/to/mcp-x",
      "env": {
        "X_API_KEY": "...",
        "X_API_KEY_SECRET": "...",
        "X_ACCESS_TOKEN": "...",
        "X_ACCESS_TOKEN_SECRET": "...",
        "MEDIA_ROOT": "/absolute/path/to/media"
      }
    }
  }
}
MCP クライアントの接続(コンテナ)

イメージを stdio で実行します。Docker では、各変数がプロセスに渡るよう、コマンドラインで -e を付けて指定する必要があります。また、MEDIA_ROOT が意味を持つのは、ディレクトリをマウントした場合のみです。

{
  "mcpServers": {
    "x": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "X_API_KEY",
        "-e", "X_API_KEY_SECRET",
        "-e", "X_ACCESS_TOKEN",
        "-e", "X_ACCESS_TOKEN_SECRET",
        "-e", "MEDIA_ROOT",
        "-v", "/host/media:/media:ro",
        "ghcr.io/role1776/mcp-x:0.1.1"
      ],
      "env": {
        "X_API_KEY": "...",
        "X_API_KEY_SECRET": "...",
        "X_ACCESS_TOKEN": "...",
        "X_ACCESS_TOKEN_SECRET": "...",
        "MEDIA_ROOT": "/media"
      }
    }
  }
}

-i は必須です。これを指定しないとコンテナに stdin が渡されず、クライアントにはサーバーがすぐに終了したように見えます。* MCP Registry 自体から*インストールするクライアントは、この呼び出しを自動で構成し、server.json で宣言された変数の入力を求めます。これはクライアント側の機能であり、このサーバーと通信できるすべてのクライアントに当てはまるわけではありません。たとえば Claude Code の CLI はレジストリからインストールしないため、上記の claude mcp add を使用してください。

クライアントに接続が切れたと表示される場合

stdio では、サーバーの stderr はクライアント側のものであり、ほとんどのクライアントはこれを破棄します。そのため、サーバーが問題を一行で明確に説明していても、こちらには次のようにしか表示されません。

✘ Failed to connect — -32000: Connection closed

同じ環境変数を設定してバイナリを手動実行し、実際の原因を確認してください。

/absolute/path/to/mcp-x -env /absolute/path/to/.env

何が問題なのかを正確に出力して終了します。どの変数が不足しているかとその入手先、キーが拒否されたこと、またはアクセストークンが読み取り専用であることが示されます。インストールの失敗は、ほぼすべてこの3つのいずれかが原因です。

HTTP で実行する

MCP_TRANSPORT=http を設定すると、サーバーは MCP_PATH(デフォルトは http://localhost:8080/mcp)で SERVER_PORT をリッスンします。

注意

HTTP トランスポートには独自の認証機能がありません。エンドポイントにアクセスできる人は誰でも、あなたのアカウントとして、あなたのクレジットを使って公開、削除、フォローを実行できます。localhost にバインドするか、認証機能のあるリバースプロキシの背後に配置してください。インターネットに直接公開しないでください。


設定

すべて環境変数で設定し、各値は起動前に検証されます。必須キーが欠けている場合、または数値以外や正の数でない値が設定されている場合は、実際に設定した変数名(APIKey ではなく X_API_KEY)を示す起動エラーになります。上限値どうしの関係は起動時に検証されません。上限値を参照してください。環境にすでに存在する変数は、.env ファイルより優先されます。

デフォルト値を設定した完全な一覧は .env.example を参照してください。コピーして .env として使用できます。

必須
環境変数備考
X_API_KEYOAuth 1.0a のコンシューマーキーです。
X_API_KEY_SECRETOAuth 1.0a のコンシューマーシークレットです。
X_ACCESS_TOKENユーザーアクセストークンです。読み取りと書き込みを設定した後に生成してください。
X_ACCESS_TOKEN_SECRETユーザーアクセストークンシークレットです。
MEDIA_ROOTx_media_upload が読み取り可能な唯一のディレクトリの絶対パスです。存在し、ディレクトリである必要があります。どちらも起動時に確認されます。意図的にデフォルト値はありません。

いずれかが不足している場合、不足している項目の一覧と Developer Console への案内を表示して起動を中止します。

MCP サーバー
環境変数デフォルト備考
MCP_TRANSPORTstdiostdio または http です。
MCP_NAMEmcp-xクライアントに通知されるサーバー名です。
MCP_PATH/mcpHTTP ルートです(http トランスポートのみ)。

クライアントに通知されるバージョンは設定できません。ビルド時に git タグからバイナリに埋め込まれます。

HTTP サーバー(http トランスポートのみ)
環境変数デフォルト
SERVER_PORT8080
SERVER_READ_TIMEOUT60s
SERVER_WRITE_TIMEOUT60s
HTTP クライアント
環境変数デフォルト備考
MAX_IDLE_CONNS_PER_HOST100X API へのコネクションプーリングです。
X_DEBUGfalse生の gotwi リクエストをログに記録します。詳細なログですが、X のエラーの意味がわからない場合に役立ちます。
ロギング
環境変数デフォルト備考
LOG_MODElocallocal → デバッグレベルのテキストハンドラー、prod → 情報レベルの JSON ハンドラーです。ログは stderr に出力されます(MCP プロトコルが stdout を使用するため、必ずそうする必要があります)。
制限

グループごとに独自の制限があるため、メディアのアップロードが遅くても、検索タイムアウトによって上限が設定されることはありません。

投稿

環境変数デフォルト備考
POSTS_MAX_QUERIES5x_posts_search/x_posts_count 呼び出しあたりのクエリ数です。
POSTS_MAX_USERNAMES5x_posts_by_user 呼び出しあたりのユーザー名数です。
POSTS_MAX_IDS100x_posts_lookup あたりの ID 数です。API 独自の上限です。
POSTS_DEFAULT_RESULTS10
POSTS_MAX_RESULTS100
POSTS_DEFAULT_DAYS7
POSTS_MAX_DAYS7最近の検索では、これより過去にさかのぼることはできません。
POSTS_DEFAULT_TIMEOUT_MS15000
POSTS_MIN_TIMEOUT_MS2000
POSTS_MAX_TIMEOUT_MS60000

ユーザー

環境変数デフォルト
USERS_MAX_USERNAMES100
USERS_MAX_IDS100
USERS_DEFAULT_RESULTS100
USERS_MAX_RESULTS1000
USERS_DEFAULT_TIMEOUT_MS15000
USERS_MIN_TIMEOUT_MS2000
USERS_MAX_TIMEOUT_MS60000

リスト

環境変数デフォルト
LISTS_DEFAULT_RESULTS25
LISTS_MAX_RESULTS100
LISTS_DEFAULT_TIMEOUT_MS15000
LISTS_MIN_TIMEOUT_MS2000
LISTS_MAX_TIMEOUT_MS60000

メディア

環境変数デフォルト備考
MEDIA_CHUNK_BYTES41943044 MB です。APPEND エンドポイントでは、セグメントの上限は 5 MB です。
MEDIA_POLL_INTERVAL_MS2000X によるトランスコード中に FINALIZE のステータスをポーリングする間隔です。
MEDIA_DEFAULT_TIMEOUT_MS120000
MEDIA_MIN_TIMEOUT_MS5000
MEDIA_MAX_TIMEOUT_MS600000大容量の動画向けの 10 分です。

各値は個別に検証され、ゼロより大きい値である必要があります。また、API 自体に上限がある値(*_MAX_IDS、POSTS_MAX_RESULTS、LISTS_MAX_RESULTS、POSTS_MAX_DAYS)は、誤入力によって X に拒否されるリクエストが発生しないよう、API の上限を超えない値にさらに制限されます。DEFAULT_*、MIN_*、MAX_* の組み合わせは、起動時に相互検証されません。整合性のない設定でもサーバーは停止せず、リクエストごとに調整されます。

  • 呼び出し元が値を省略するか、ゼロまたは負の値を渡した場合、対応する DEFAULT_* にフォールバックします。
  • その後、値は [MIN_*, MAX_*] の範囲内に制限されます。そのため、DEFAULT_* が MAX_* より大きい場合は、MAX_* が適用されます。
  • MIN_* が MAX_* を超える場合は、最大値が優先されます。

したがって、有効な制限は常に設定された最大値の範囲内となり、設定ミスがあっても起動に失敗するのではなく、動作するサーバーとして稼働します。その代わり、設定ミスが通知されずに処理されます。たとえば、POSTS_MAX_RESULTS=10 の代わりに POSTS_MAX_RESULTS=1 と設定しても警告は出ず、応答件数がひっそりと少なくなるだけです。結果が途中で切れているように見える場合は、これらの値を再確認してください。


アーキテクチャ

このプロジェクトは、クリーンな階層構造を採用しています。依存関係はドメインに向かい、各レイヤーはインターフェースを介して次のレイヤーと通信します。

app/                       the Go module: sources plus its build files
                           (Dockerfile, .dockerignore, .goreleaser.yaml)

cmd/mcp-x/main.go          entry point: parse flags, load config, run app

internal/
  app/                     wiring + lifecycle (X client, bootstrap, run, graceful shutdown)
  config/                  config loading (.env → env vars → validate → env-name error messages)
  domain/x/                core types and errors
    posts/ users/ lists/ media/   value objects: PostID, UserID, Username, Draft, Query, Upload…
    format.go              shared snowflake-id and username validation
    errors.go              the sentinel error set the whole app maps onto
  dto/x/                   request/response shapes for the MCP tools, with jsonschema + validate tags
  transport/mcp/           MCP layer
    router/                registers every tool group on the MCP server
    x/posts|users|lists|media/   tool definitions, handlers and error → tool-result mapping
  usecase/x/               business logic: validation, parallelism, timeouts, limit resolution
  adapter/x/               X API wiring
    client/                gotwi client + startup Bootstrap (key check, key-owner id)
    apierr/                X problem responses → domain errors
    posts|users|lists|media/     endpoint calls and mappers to DTOs
  pkg/                     reusable building blocks (mcpserver, server, logger, validator, parallel)

ツール呼び出しのリクエストフロー:

MCP client → transport/mcp/x/... (handler) → usecase/x/... → adapter/x/... → gotwi → X API
                    ↑ maps errors                 ↑ validates, resolves limits,
                      to isError text               fans out, applies timeouts

特に重要な境界が 2 つあります。

  • ドメイン層では無効な値の生成が拒否されます。 NewPostID、NewUserID、NewUsername、NewDraft などは生成時に検証されるため、不正な ID や 300 文字の投稿は、リクエストを消費する前にローカルで拒否されます。ID はスノーフレーク形式に照らして検証され、ユーザー名は X の 1~15 文字の [A-Za-z0-9_] というルールに照らして、共通の format パッケージで検証されます。
  • すべてのレイヤーで同じエラーの語彙が使われます。 アダプターは X の問題応答を domain/x/errors.go のセンチネルエラーに変換します。センチネルエラーを人間が読めるテキストに変換するのは、トランスポート層だけです。そのため、どの 42 個のツールで発生した場合でも、同じエラーは同じ内容で表示されます。

開発

Go のコードはすべて app/ にあります。リポジトリのルートから makefile を使うか、ツールチェーンに -C app を渡してください。

make build          # compile the binary -> bin/mcp-x
make test           # go test -v ./...
make cover          # total coverage percentage
make cover-html     # coverage report in the browser
make version        # the version that would be stamped into the binary

go -C app build ./...
go -C app test ./...
go -C app vet ./...

モックは、各 usecase インターフェースの隣にある //go:generate ディレクティブを使って mockgen で生成します。

go -C app generate ./...

新しいコードにはテストを付ける必要があります。 プルリクエストのガイドライン全体については、CONTRIBUTING.md を参照してください。

ライセンス

MIT License のもとで公開されています。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。