mcpField
X
x-mcp

x-mcp

github.com/starchild-ai-agentマーケティング・グロース3067 回インストール6 日前に更新
リポジトリ

x-mcp について

x-mcpは、自分のXアカウントを操作するエージェント向けスキルです。公式ホストのX MCPで読み取り、本人のアプリとOAuth認証情報を使ってREST APIで書き込みます。認証情報はローカルに保存されます。

主な機能

  1. 01X MCPで投稿、ユーザー、トレンドを検索
  2. 02タイムライン、メンション、ブックマークを取得
  3. 03REST APIで投稿、返信、削除
  4. 04いいね、リポスト、フォロー、DM送信
  5. 05個人のアプリとOAuth認証情報を使用

活用シーン

  1. 01自分のタイムラインやメンションを検索・確認
  2. 02自分のアカウントから投稿や返信
  3. 03投稿へのいいね、リポスト、ブックマーク
  4. 04Xでダイレクトメッセージを送信

MCP 対応

ホスト型X MCPの24個の読み取りツールを使用します。書き込み操作はMCPではなく、X v2 REST APIで行います。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/starchild-ai-agent/official-skills --skill x-mcp

インストール後、Claude Code で/x-mcpを入力して読み込まれたか確認します。

同梱ファイルscripts/oauth_driver.py

詳細

X API — MCP(読み取り)+ REST(書き込み)、BYOK

ユーザー自身の X 開発者アプリを接続し、このエージェントが以下を実行できるようにします:

  • 読み取り — 公式ホスト型 X MCP(https://api.x.com/mcp)経由 — 24 個のツール
  • 書き込み — X v2 REST API(https://api.x.com/2/...)経由 — 投稿 / 削除 / いいね / リツイート / 返信 / DM

BYOK である理由(共有の Starchild アプリではない): X の書き込みアクセスはアプリごとに レート制限され(アプリ全体の上限)、従量課金がアプリ所有者に請求され、TOS 上の責任も アプリ所有者に帰属します。共有アプリ = 単一障害点 + 相互にリソースを奪い合う + 請求の集中 + コンテンツモデレーションの責任。そのため、すべてのユーザーが自身のアプリ + OAuth トークンを持ち込みます。トークンはこのマシン上にのみ存在し(~/.xurl、 永続ワークスペースにシンボリックリンク — STEP 3 を参照)、 プロキシ経由で渡されることはありません。

このスキルを使うべきとき

ユーザーが自身のアカウント / アプリで X を操作したい場合に使用します:

  • 「私の X / Twitter アカウントを接続して、代わりに投稿できるようにして」
  • 「私の開発アプリで X API をセットアップして」「私の X 開発者キーを使って」
  • 「最近のツイートを検索して / タイムラインを読んで / メンションを読んで」(自身のアプリで)
  • 「私として X で投稿 / 返信 / いいね / リツイート / DM して」
  • 「このツイートをブックマークして」

使用しないでください — 代わりに適切な選択肢を選んでください:

  • 「このツイートを要約して」/「@user は何を投稿している?」/ キャッシュタグのスキャン、アカウント不要 → twitter スキルを使用(twitterapi.io 経由の読み取り専用スクレイピング、OAuth 不要)
  • 「X / Grok のモデルを追加して」→ それは xai-grok-onboarding(チャットモデル)であり、無関係
  • ユーザーが X 開発者アプリを持っておらず、作るつもりもない → twitter スキル、または 書き込みには自身のアプリが必要であることを説明する

曖昧さの解消:twitter = 読み取り専用、セットアップ不要、誰の公開ツイートでも可。x-mcp = ユーザー自身の認証済みアカウント、書き込み可能、初回のみの OAuth セットアップが必要。

関連項目

  • twitter スキル — 任意の公開ツイートに対する読み取り専用 X スクレイピング(アカウント不要、OAuth 不要)
  • config/context/references/model-onboarding.md — ユーザーが実際には X データ API ではなく チャットモデル(Grok)を意図していた場合

プリフライト — ビルド互換性(開始前に確認)

このスキルは 2 つのプラットフォーム機能を利用します。セットアップ前に両方を確認してください:

  1. ネイティブ MCP クライアント(読み取りに必須)。 starchild-clawd に core/mcp/* が含まれ、agent.yaml から defaults.mcp_servers を読み取る必要があります。簡単な確認: /mcp を実行 — ステータスブロックが返れば、クライアントは存在します。/mcp が不明または エラーになる場合、実行中のビルドは MCP サポートより前のもの → MCP 経由の読み取りは機能しません。REST 書き込みパス(xurl)はそれに関係なく機能します。または、プラットフォームイメージを更新してください。
  2. ターンごとのホットリロード(自動トークン更新に必須)。 約 2 時間のトークンローテーションが 自動的に再接続するために必要です(STEP 7)。これがないビルドでも機能しますが、 各更新後に手動で /mcp reload が必要です — STEP 7 にフォールバックとして記載されています。 クリーンなランタイムプローブはありません。現在のビルドにはこれがあると想定し、 「更新の約 2 時間後に MCP が静かに停止し、/mcp reload でのみ復活する」を ビルドにターンごとのフックがないシグナルとして扱ってください。

どちらの MCP 機能も存在せず、ユーザーが公開ツイートを読み取るだけの必要しかない場合は、 ここで停止し、代わりに twitter スキルを使用してください — ビルドサポートは不要です。

読み取りと書き込み — 2 つの別個のシステム

機能チャネル検証済み
投稿 / ユーザー / ニュースの検索、タイムライン、メンション、トレンド、ブックマークMCP(24 個のツール)接続済み
投稿 / 削除 / 返信 / いいね / リツイート / フォロー / DMREST /2/...(MCP には含まれない)投稿 + 削除をテスト済み

MCP の tools/list は 24 個の読み取り / ブックマークツールのみを返します。書き込みエンドポイントは docs.x.com で文書化された別個の REST API です — これらは MCP 経由で検出可能ではありません。 これらはこのスキルの以下に記載されています。


STEP 1 — ユーザーが X ポータルで OAuth 2.0 認証情報を作成する(手動。X にはこのための API はありません)

X はアプリを作成/設定するための API を公開していません。これらの手順は Web ポータルでの手動作業が避けられません。コピー&ペーストで正確に行えるようにしてください。

  1. developer.x.com にアクセス → アプリを作成/開きます。
  2. 表示されるデフォルトのキー(API Key / API Secret / Bearer Token)は OAuth 1.0a であり、私たちが使用するものではありません。
  3. アプリの Settings タブ → User authentication settings → Set up。次のとおりに正確に入力します:
    • App permissions: Read and write(ユーザーが DM を希望する場合は DM を追加)
    • Type of App: Web App, Automated App or Bot → Confidential client(これが Client Secret を生成する設定です。Native/Public では生成されません)
    • Callback URI / Redirect URL: http://localhost:8080/callback(xurl のリスナーとバイト単位で一致している必要があります)
    • Website URL: https://iamstarchild.com(純粋に表示用のメタデータであり、認証には使用されません。一意である必要もありません — すべてのユーザーが同じ値を使用でき、技術的な影響はゼロです)
  4. Save → X が Client ID + Client Secret を一度だけ 表示します。Secret は一度しか表示されないので、すぐにコピーしてください。
2 つの URL が実際に制御するもの(ユーザーに回答できるように)
  • Callback URI = X が OAuth 認証コードを返す場所です。xurl は localhost:8080 でローカルリスナーを起動します。コードはユーザー自身の マシン上でブラウザー→xurl へと流れ、外部サーバーを経由することはありません。両側が同一でない場合、X は redirect_uri_mismatch を返します。
  • Website URL = 表示専用のメタデータです。認証の一部ではなく、 一意性の検証もされません。すべてのユーザーが https://iamstarchild.com に設定しても安全です。

STEP 2 — 認証情報を安全に収集する

request_env_input(チャットでキーを尋ねることは絶対にしないでください):

  • X_OAUTH_CLIENT_ID — X アプリの Client ID(OAuth 2.0)
  • X_OAUTH_CLIENT_SECRET — X アプリの Client Secret(OAuth 2.0)

ユーザーに次のことを忘れずに伝えてください:これは OAuth 2.0 のペア(User authentication settings + Confidential を有効にした後のもの)であり、API Key/Secret(1.0a)でも Bearer Token でもありません。

STEP 3 — xurl をインストールし、認証情報ストアを永続化し、アプリを登録する

⚠️ 永続化は必須であり、任意ではありません。 xurl はアプリの登録と OAuth トークンの両方を ~/.xurl(すなわち /root/.xurl)に保持します。/root は エフェメラル であり、 コンテナが再起動するたびに消去されます。そのため、この手順を行わないと、ユーザーは次回の再起動で接続(さらにはアプリの登録)を失い、最初から OAuth をやり直す必要があります。 実際のファイルは永続ワークスペースに置き、起動のたびにシンボリックリンクを張り直してください。xurl はシンボリックリンク越しに書き込みます(検証済み)ので、すべての xurl 呼び出しは透過的に永続ファイルを使用します — コマンドごとに HOME を前置する必要はありません。

npm install -g @xdevplatform/xurl          # validated v1.2.2

# Persist install + credential store across container restarts (idempotent).
# Append ONCE to workspace/setup.sh (which re-runs at every boot):
cat >> setup.sh <<'SH'
npm install -g @xdevplatform/xurl
# X (xurl) credential store: /root is ephemeral, keep ~/.xurl in the workspace
XURL_STORE=/data/workspace/.config/x-mcp/xurl_store
mkdir -p "$(dirname "$XURL_STORE")"; chmod 700 "$(dirname "$XURL_STORE")" 2>/dev/null || true
if [ -f /root/.xurl ] && [ ! -L /root/.xurl ]; then mv /root/.xurl "$XURL_STORE"; fi
ln -sf "$XURL_STORE" /root/.xurl
SH

# Run it now so the store is live for this session BEFORE registering the app:
XURL_STORE=/data/workspace/.config/x-mcp/xurl_store
mkdir -p "$(dirname "$XURL_STORE")"; chmod 700 "$(dirname "$XURL_STORE")" 2>/dev/null || true
if [ -f /root/.xurl ] && [ ! -L /root/.xurl ]; then mv /root/.xurl "$XURL_STORE"; fi
ln -sf "$XURL_STORE" /root/.xurl

xurl auth apps add starchild-x \
  --client-id "$X_OAUTH_CLIENT_ID" \
  --client-secret "$X_OAUTH_CLIENT_SECRET" \
  --redirect-uri "http://localhost:8080/callback"

xurl auth status      # confirm app registered, redirect_uri shows [app config]
ls -la /data/workspace/.config/x-mcp/xurl_store   # confirm store lives in workspace

STEP 4 で取得した OAuth トークンはこの同じ永続ファイルに保存されるため、一度接続すれば 接続は再起動をまたいで維持されます。(agent.yaml の MCP ベアラーは別物で、すでにワークスペースに存在します。STEP 7 のリフレッシュタスクが両方を同期させ続けます。)

STEP 4 — ヘッドレス OAuth(このマシンにはブラウザーがない → ユーザーが URL を貼り付けて返す)

xurl auth oauth2 --headless は認証 URL を表示し、その後 stdin でブロックして 貼り付けられたコードを待ちます。コードは そのプロセスのメモリ内にのみ存在する PKCE code_verifier に紐づけられています — ユーザーが貼り付けて返す前にプロセスが終了すると、 そのコードは決して交換できません。したがって、フロー全体で「URL を表示」から 「コードを交換」までを通じて 1 つの xurl プロセスを生き続けさせる必要があります。

永続ドライバーパターン

subprocess.PIPE を介して xurl の stdin を開いたまま保持する単一の Python ドライバーを実行し、 認可 URL をファイルに書き込み、コードファイルを最大約 10 分間待機してから、コードを渡して 結果をキャプチャします。主要な形は次のとおりです。

proc = subprocess.Popen(["xurl","auth","oauth2","--app","starchild-x","--headless"],  # no USERNAME (see token-key note)
    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0)
# 1) read stdout until the oauth2/authorize line → write it to /tmp/xurl_auth_url.txt
# 2) poll /tmp/xurl_code_input.txt (up to 600s) for the pasted callback URL/code
# 3) proc.stdin.write(code+"\n"); flush  → 4) read result → write /tmp/xurl_oauth_done.json

このスキルに同梱されているドライバー(skills/x-mcp/scripts/oauth_driver.py)を インラインで書き直すのではなく使用してください。そうすることで、USERNAME なしの起動と 600 秒の タイムアウトが一貫して保たれます。180 秒のフォアグラウンド制限を超えて生存するように起動してください — stdout をファイルにリダイレクトし、デタッチし、フォアグラウンドの bash をそれでブロックしないでください:

# clean any stale driver/xurl FIRST (see driver rule 1), then:
python3 skills/x-mcp/scripts/oauth_driver.py >/tmp/oauth_driver_console.log 2>&1 &
sleep 8
cat /tmp/xurl_auth_url.txt        # the URL THIS live driver just wrote — give the user THIS one
pgrep -f oauth_driver.py >/dev/null && echo "driver alive, waiting for code"

ドライバーは xurl auth oauth2 --app starchild-x --headless(USERNAME 引数なし)を実行し、 認可 URL を /tmp/xurl_auth_url.txt にキャプチャし、/tmp/xurl_code_input.txt を最大 600 秒(約 10 分)待機して、 コードを渡し、結果を /tmp/xurl_oauth_done.json に書き込みます。

トークンのキー = 解決された X ハンドル。 USERNAME が渡されたかどうかに関係なく、 xurl は /2/users/me を介してアカウントを解決し、トークンを空文字列のキーではなく、 解決された X ハンドル(例: oauth2_tokens['ud_noel'])の下に保存します。キーはハードコードせず 動的に読み取ってください。トークンを読み取るすべての箇所でこのヘルパーを使用してください — これはトークンがちょうど 1 つであることを想定しており、複数見つかった場合は停止してハンドルを 一覧表示するので、どのアカウントを使用するかを確認したり、古いものをクリアしたりできます:

import yaml, os

def _xurl_token(app="starchild-x"):
    d = yaml.safe_load(open(os.path.expanduser("~/.xurl")))
    toks = d["apps"][app]["oauth2_tokens"]          # {'<handle>': {...}}
    keys = list(toks)
    if not keys:
        raise SystemExit(f"No OAuth token for app '{app}' — run STEP 4 first.")
    if len(keys) > 1:
        raise SystemExit(
            f"Multiple X accounts authorized under '{app}': {keys}. "
            "Confirm which handle to use (or remove stale tokens) before continuing.")
    return keys[0], toks[keys[0]]["oauth2"]          # (handle, {access_token, refresh_token, expiration_time})
OAuth ドライバーのルール
  1. 一度に正確に 1 つのドライバーを実行してください。 開始する前に、古い xurl auth oauth2 / oauth_driver の PID を正確な PID で、現在のシェルを除外して強制終了してください。 ここでは pkill -f oauth_driver.py を避けてください — そのパターンはクリーンアップコマンド自身の シェルにも一致してしまいます。次を使用してください:
    SELF=$$
    for pat in "xurl auth oauth2" "oauth_driver.py"; do
      for pid in $(pgrep -f "$pat"); do [ "$pid" != "$SELF" ] && kill "$pid" 2>/dev/null; done
    done
    rm -f /tmp/xurl_auth_url.txt /tmp/xurl_code_input.txt /tmp/xurl_oauth_done.json /tmp/xurl_oauth.pid
    
  2. ユーザーには、稼働中のドライバーが今書き込んだ URL のみを渡してください — このドライバーの 起動後に /tmp/xurl_auth_url.txt から読み取ってください。以前の試行やチャット履歴から URL を貼り付けないでください。
  3. 再起動した場合、以前の認可 URL は無効です。 ユーザーにそれを破棄し、最新のものだけを 使用するよう伝えてください。
  4. 交換が失敗した場合は、state が一致することを確認してください: ユーザーが貼り付けた コールバックの state= は、稼働中のドライバーが生成した URL の state= と等しくなければ なりません。不一致は、コールバックが古い認可 URL から来たことを意味します。

ユーザーに、表示される返信で明確に伝えてください:

  1. 任意のデバイスのブラウザーで https://x.com/i/oauth2/authorize?... の URL(稼働中のドライバーが 書き込んだもの)を開いてください。
  2. Authorize app をクリックしてください。
  3. ブラウザーは http://localhost:8080/callback?state=...&code=... にリダイレクトします — ページは 読み込みに失敗します(これはこのリモートボックスの localhost であり、ユーザーのブラウザーからは 到達できません)。これは想定どおりです。コードはアドレスバーにあります。
  4. アドレスバーから完全なリダイレクト URL をコピーし、チャットに貼り付けて返してください。

それを待機中のドライバーに渡してください:

echo '<full redirected URL with code=>' > /tmp/xurl_code_input.txt

ドライバーはそれを ~/.xurl のトークンと交換し、/tmp/xurl_oauth_done.json を書き込みます。 「could not resolve username via /2/users/me」という警告は失敗ではありません — それは以下の 登録の罠です。

STEP 5 — client-not-enrolled 登録ゲート

xurl --app starchild-x /2/users/me は次を返します:

{"reason":"client-not-enrolled","title":"Client Forbidden",
 "detail":"...App that is attached to a Project..."}

OAuth は成功しましたが、アプリに v2 API へのアクセス権がありません。ポータルで修正します(手動):

  • Free ティア: ダッシュボードで無料アプリを直接 Pay-per-use に移動できます — これで v2 へのアクセス権が付与されます。必要なゲートは Pay-per-use / Production への登録です。Pay-per-use ではカードの登録が必要になる場合があります。
  • 登録後は、再認証は不要です — トークンは保持されます。テストを再実行するだけです。 反映には 1〜2 分かかることがあります。

確認: xurl --app starchild-x /2/users/me は client-forbidden ではなく、ユーザーオブジェクト(id、name、 username)を返す必要があります。

STEP 6 — MCP を agent.yaml に組み込む(ネイティブ MCP クライアント。エージェントコードの変更は不要)

starchild-clawd にはネイティブ MCP クライアント(core/mcp/*: stdio / streamable-http / sse + 静的な headers)があります。defaults.mcp_servers:(またはユーザーの agent.yaml)の下に追加します:

defaults:
  mcp_servers:        # MAPPING keyed by server name (NOT a YAML list)
    xmcp:
      transport: streamable-http
      url: https://api.x.com/mcp
      headers:
        Authorization: "Bearer <ACCESS_TOKEN_FROM_~/.xurl>"
      timeout: 30

mcp_servers はマッピング(サーバー名 → 定義)であり、リストではありません。リスト 形式(- name: xmcp)は黙って無視されます(must be a mapping, got list とログに記録されます)。

次に /mcp を実行して、24 個のツールが mcp__xmcp__<tool> として登録されることを確認します。

STEP 7 — トークンの有効期限と自動リフレッシュ

OAuth2 のアクセストークンは約 2 時間で期限切れになります(offline.access スコープは refresh_token を付与するため、更新は可能です)。agent.yaml の headers 内の bearer は静的であり、 トークンの値を自動でリフレッシュするものは何もありません。現在のトークンを agent.yaml に貼り付けただけでリフレッシュしなければ、MCP は約 2 時間で停止します。 bearer を書き換えるリフレッシュ ループを実行する必要があります。(新しい bearer での再接続は現在の clawd では自動です — 以下の「現在の clawd での自動リロード」を参照 — ただしトークン自体は依然として リフレッシュして書き込む必要があります。)

xurl でリフレッシュし、その後 agent.yaml の bearer を書き換えます(再接続は自動です):

# read current access token after xurl refreshes it
xurl --app starchild-x /2/users/me >/dev/null 2>&1   # xurl auto-refreshes when near expiry on use
# read the token via the _xurl_token() helper from STEP 4 (single-token check + handle-keyed lookup)
ACCESS=$(python3 -c "
import yaml, os
d = yaml.safe_load(open(os.path.expanduser('~/.xurl')))
t = d['apps']['starchild-x']['oauth2_tokens']
keys = list(t)
assert len(keys) == 1, f'expected one X account, found {keys} — confirm/clean before refresh'
print(t[keys[0]]['oauth2']['access_token'])
")
# patch agent.yaml header to the fresh token (a small python/yaml rewrite).
# On current clawd that's all — the next chat turn auto-reconnects (see below).
リフレッシュの仕組み
  • Confidential クライアントのリフレッシュ: POST https://api.x.com/2/oauth2/token を HTTP Basic 認証(base64(client_id:client_secret))とボディ grant_type=refresh_token&refresh_token=<rt> で送信します。新しい access_token (expires_in 7200)と、新しくローテーションされた refresh_token が返されます。
  • refresh_token はリフレッシュのたびにローテーションされます — 古いものは無効化されます。新しい refresh_token を (~/.xurl に)永続化する必要があります。そうしないと次のリフレッシュが失敗します。
  • ✅ xurl 自身の使用時リフレッシュを優先してください(xurl --app starchild-x /2/users/me): xurl は 期限切れ間近になるとリフレッシュし、ローテーションされたトークンを ~/.xurl に自ら書き戻します。 シンボリックリンクを通して(確認済み) — 永続性は保たれ、ファイルに触れる必要はありません。
  • 🚫 もし ~/.xurl を自分で書き込む場合、絶対にアトミックリネームでの書き込みを使わないでください (tempfile + os.replace/os.rename)。~/.xurl は永続ワークスペースストアへの シンボリックリンクであるため(STEP 3)、リネームはシンボリックリンクを一時的な /root 内の通常の ファイルに置き換えます — 永続性が黙って壊れ、トークンは次の再起動時に消えます。(これは ChatGPT/Grok の store.py が 使う標準的な「安全な」パターンです — 実際のファイルには正しく、シンボリックリンクには致命的です。)確認済み: os.replace は シンボリックリンクを破壊します。インプレースの open(path,"w") と xurl はどちらもそれを通過して書き込みます。したがって インプレースでのみ書き込んでください:
    # safe: follows the symlink, lands in the persistent workspace store
    with open(os.path.expanduser("~/.xurl"), "w") as f:
        yaml.safe_dump(data, f)
    
現在の clawd における自動リロード

現在の starchild-clawd は、/chat および /chat/stream の各ターンの開始時に maybe_hot_reload() を呼び出します(mtime でゲートされ、安価な単一 stat です)。したがって、リフレッシュタスクが agent.yaml の bearer を書き換えた後、次のチャットターンで新しいトークンを使って自動的に再接続されます — ユーザーが /mcp reload を実行することは決してありません。 MCP サーバー設定のシグネチャにはソート済みのヘッダーが含まれるため、bearer の変更は再接続として正しく分類されます。

そのため、リフレッシュタスクが行う必要があるのは次の 2 つだけです。

  1. トークンをリフレッシュし(Basic 認証)、ローテーションされた refresh_token を ~/.xurl に永続化する(インプレース書き込み、または xurl 経由のみ — アトミックリネームは不可。上記のシンボリックリンクに関する警告を参照)、
  2. 新しい access_token を agent.yaml の headers.Authorization bearer に書き込む(agent.yaml はすでにワークスペース内にあるため、そこでのアトミック書き込みは問題ありません)。

/mcp reload は不要で、手動の手順もありません。(スケジュールされたタスクは接続自体をリロードできません — タスクの run.py は別プロセスであり、インプロセスの MCP マネージャーシングルトンに触れることができないためです — ただしその必要はありません。ターンごとのフックが再接続を処理します。)

ターンごとのホットリロードがない古い clawd ビルド: ターンごとの maybe_hot_reload() 呼び出しより前のビルドを実行している場合、誰かが /mcp reload を実行するまで、ライブ接続は新しい bearer を取得しません — その場合は、リフレッシュタスクに加えてリロードをトリガーさせるか、約 2 時間ごとのリフレッシュ後に毎回 /mcp reload を実行するようユーザーに指示してください。

リフレッシュを約 60〜90 分ごとの scheduled_task として設定します(トークンの有効期限は約 2 時間): トークンをリフレッシュ(Basic 認証)→ ローテーションされた refresh_token を ~/.xurl に永続化 → 新しい access_token を agent.yaml の bearer に書き込む。現在の clawd ではこれが完全に自動です。

トークンストアのパス: ~/.xurl → apps.starchild-x.oauth2_tokens['<resolved-handle>'].oauth2.{access_token,refresh_token,expiration_time}。 キーは xurl が /2/users/me から解決する X ハンドル(例: 'ud_noel')であり、空文字列ではありません — STEP 4 の _xurl_token() ヘルパーを介して動的に読み取ってください(通常はアプリごとに 1 つのトークンです。複数ある場合はヘルパーがそのケースを通知するので、選択・クリーンアップできます)。 ~/.xurl は永続的な /data/workspace/.config/x-mcp/xurl_store(STEP 3 で設定)へのシンボリックリンクです — ~/.xurl を通常どおり読み書きしてください。永続化は透過的に行われます。


REST 書き込みエンドポイント(MCP には含まれない — 同じトークンで xurl 経由で呼び出します)

すべて OAuth2 bearer で認証されます。xurl が認証とリフレッシュを自動的に処理します。

アクションメソッド + エンドポイントボディ / 備考ステータス
ツイートを投稿POST /2/tweets{"text":"..."}tested
返信POST /2/tweets{"text":"...","reply":{"in_reply_to_tweet_id":"<id>"}}documented
引用POST /2/tweets{"text":"...","quote_tweet_id":"<id>"}documented
ツイートを削除DELETE /2/tweets/{id}—tested
いいねPOST /2/users/{user_id}/likes{"tweet_id":"<id>"}documented
いいね解除DELETE /2/users/{user_id}/likes/{tweet_id}—documented
リツイートPOST /2/users/{user_id}/retweets{"tweet_id":"<id>"}documented
フォローPOST /2/users/{user_id}/following{"target_user_id":"<id>"}documented
DMPOST /2/dm_conversations/with/{participant_id}/messages{"text":"..."}documented

例(xurl 経由で投稿):

xurl --app starchild-x -X POST /2/tweets -d '{"text":"hello from my agent"}'

いいね/リツイート用の user_id = /2/users/me から取得した認証済みユーザーの id です。 「documented」とマークされたエンドポイントは docs.x.com からのものであり、ここではまだ往復テストされていません — 最初の実際の使用時に検証し、tested とマークしてください。

24 個の MCP READ ツール(mcp__xmcp__<tool> として登録されます)

検索/ニュース: search_posts_all、search_news、get_news、search_users、 get_trends_by_woeid、get_posts_counts_recent。 投稿: get_posts_by_id、get_posts_by_ids、get_posts_liking_users、 get_posts_quoted_posts、get_posts_reposted_by。 ユーザー: get_users_me、get_users_by_id、get_users_by_username、 get_users_by_usernames、get_users_timeline、get_users_posts、 get_users_mentions。 ブックマーク(書き込み系): get_users_bookmarks、get_users_bookmarks_by_folder_id、 get_users_bookmark_folders、create_users_bookmark、create_users_bookmark_folder、 delete_users_bookmark。

共通パラメータ: max_results、*.fields(カンマ区切りリスト)、expansions。search_posts_all は query を受け取ります(from:、min_faves:、$CASHTAG などの演算子をサポート)。


FAQ

  • 「OAuth 1.0a アプリしか表示されない/Client ID がない。」 User authentication settings を有効化していません。有効化するまで、Keys & tokens には 1.0a しか表示されません。STEP 1 を参照してください。
  • redirect_uri_mismatch。 ポータルの Callback URI ≠ http://localhost:8080/callback です。 完全に同一である必要があります。
  • Client Secret が提示されない。 Type of App が Native/Public になっています。 Confidential(Web App / Bot)に切り替えてください。
  • OAuth 成功後に client-not-enrolled。 アプリに v2 アクセスがありません → Move to Pay-per-use を実行してください(STEP 5)。
  • コールバックページが読み込まれない。 想定どおりです — これはリモートマシンの localhost です。 コードはアドレスバーにあります。URL 全体をコピーして貼り戻してください。
  • MCP が動作した後、約 2 時間で停止した。 アクセストークンが期限切れになり、 agent.yaml 内の bearer が古くなっています。bearer を書き換えるリフレッシュタスクを設定してください(STEP 7)— 現在の clawd では、次のチャットターンで自動的に再接続され、/mcp reload は不要です。
  • MCP 経由で投稿できますか? いいえ。書き込みは REST /2/... 経由で行います(表を参照)。MCP は 読み取り + ブックマークのみです。

重要なルール

  • access_token や refresh_token を絶対にチャットに出力しないでください。 これらは ~/.xurl 内の 永続的な認証情報です。設定を表示する際は、bearer をマスクしてください (Bearer S0tHdk…)。トークンがプロキシやチャット履歴を経由することはありません。
  • Client ID / Secret を絶対にチャットで尋ねないでください。 常に request_env_input 経由で収集します(STEP 2)。
  • OAuth ステップを自動ポーリングしたり急かしたりしないでください。 認可 URL を出力したら、 ユーザーが承認してリダイレクト URL を貼り戻すまで待機します。ユーザーが貼り付ける前に コードファイル(/tmp/xurl_code_input.txt)を書き込むと、ドライバーが空の入力で待機してしまいます。
  • client-not-enrolled の場合は、盲目的に再試行しないでください。 これはポータルの登録ゲート (STEP 5)であり、一時的なエラーではありません — 同じ呼び出しを再試行しても失敗し続けます。ユーザーを Move to Pay-per-use へ誘導し、その後一度だけ再テストしてください。
  • 書き込みは REST であり、MCP ではありません。 create_post MCP ツールを探さないでください — 存在しません。 REST の表を使用してください。
  • トークンはリフレッシュのたびにローテーションします。 常に新しい refresh_token を永続化してください。そうしないと 次のリフレッシュが失敗します(STEP 7)。

更新ポリシー(X が変更されたら → このスキルをバージョンアップ)

以下のいずれかが変更された場合に更新 + バージョンアップします(その後 PR を作成し、main に絶対にプッシュしないでください):

  • MCP ツールセット(ツールの追加/名前変更/削除、スキーマ変更)→ MINOR
  • REST 書き込みエンドポイント(パス/ボディの変更)→ MINOR、シグネチャが破壊される場合は MAJOR
  • X ポータルの登録フロー(Pay-per-use、認証設定の UI/ステップ)→ PATCH/MINOR
  • xurl CLI のフラグ/動作 → PATCH/MINOR

独立性(スキルのみ、エージェントコードの変更なし)

このスキルはエージェントコードの変更を必要としません。すでにネイティブの MCP クライアント(core/mcp/*)と、純粋な設定(agent.yaml の mcp_servers)、およびスケジュールされた リフレッシュタスクに依存しています — これらはすべて、このスキルに従ってエージェントが編成します。唯一の前提条件は、 実行中のビルドに MCP クライアントが含まれていることです。ユーザー自身のアプリを使わない読み取り専用のスクレイピング → 代わりに twitter スキルを使用してください。

検証済み: xurl 1.2.2 · MCP サーバー xmcp 1.0.0(プロトコル 2025-06-18)· 24 ツール · アクセスレベル read-write-directmessages · デフォルトリダイレクト http://localhost:8080/callback。

コメント