Skip to content

運用確認bot MCP(Cursor) ​

当日・前日の日別記事が下書きのままか公開済みか、考察フィールドが埋まっているか、毎朝の取込が済んだか、新台情報取得がどうだったかを、wp-admin にログインせずに Cursor エージェント(運用確認bot)から確認するための MCP です。WordPress の REST API ops-status/v1(GET のみ)を、読み取り専用ロールのユーザーのアプリケーションパスワードで呼びます。編集用・取込用・管理者のアカウントは渡しません。

関連: Issue #3874 / 設計 API-006 運用確認 REST / ADM-035 権限管理画面

できること・できないこと ​

操作運用確認bot
日別記事の状態(下書き・予約・レビュー待ち含む)と考察欄の入力有無できる
日別記事 1 件の考察欄の本文(明示したときだけ)できる
ホールごとの db2023 最新日と取込履歴できる
新台情報取得の最終実行結果と未紐付け件数できる
アプリケーションパスワード経由(REST・XML-RPC)と wp-admin での書き込み(記事・取込・新台情報・自分のプロフィールやアプリケーションパスワードの変更を含む)できない
日別記事の本文(post_content)・有料記事・会員情報・設定値の取得できない
wp-admin を開く(ダッシュボード・記事一覧・プロフィールを含む)できない

運用確認bot ロール(ops_status_reader)が持つのは WordPress の read と read_ops_status だけです。wp-admin を開くとサイトトップへリダイレクトされます。

WordPress は read だけのユーザーにも自分のプロフィール編集とアプリケーションパスワードの発行を許すため、ops_status_reader などの REST 用 bot ロールだけを持つユーザーには BotWriteGuardHooks で次の制限をかけています(詳細は API-006 の「権限・nonce・レート制限」)。

  • REST は GET / HEAD / OPTIONS 以外を 403(/wp/v2/users/me の更新、アプリケーションパスワードの発行・削除を含む)
  • 自分自身に対する edit_user とアプリケーションパスワードの発行・編集・削除の権限を外す(管理者による取り消しはできる)
  • XML-RPC にはログインできない(wp.editProfile 等も使えない)
  • x_announcer や birthday_linker を併せ持つユーザーは、そのロールに許された書き込みも通り、拒否時のエラーコードはそのロールのもの(x_announce_write_forbidden / birthday_write_forbidden 等)になる

自分自身の edit_user を外しているため、自分のアプリケーションパスワードの一覧・取得(REST の GET)もできません。パスワードの確認・取り消しは管理者が行います。

ログインパスワードには注意してください。 上の制限はアプリケーションパスワードでのアクセスと wp-admin が対象です。ログインパスワードで wp-login からブラウザにログインすると、フロントの会員プロフィール・退会フォームやコメント投稿などは使えてしまいます。運用確認bot ユーザーのログインパスワードは長いランダムな値にし、どこにも保存せず使わないでください。bot にはアプリケーションパスワードだけを渡します。

運用手順(WordPress 側) ​

bot が叩く WordPress(通常は本番)で、管理者が次の作業をします。

1. 運用確認bot ユーザーを作る ​

  1. 管理画面 → ユーザー → 新規追加
  2. ユーザー名は用途が分かる名前にする(例: ops-status-bot)。メールアドレスは管理者が受け取れるものにする
  3. 権限グループで「運用確認bot」を選んで追加する
  4. パスワードは長いランダムな値を生成したまま、控えずに追加する(ログインパスワードは使わない。bot にはアプリケーションパスワードだけを渡す)

bot ごと・用途ごとにアカウントを分けてください。 日別記事編集bot・取込担当・新台情報担当のアカウントに read_ops_status を足して兼用しないこと。編集用のアプリケーションパスワードが漏れても確認用には影響せず、その逆も同じにするためです。運用確認bot ロールの Capability は ADM-035 権限管理画面 で確認できます(既定は「運用状態の確認」のみ)。

2. アプリケーションパスワードを発行する ​

運用確認bot ユーザーは wp-admin を開けないため、管理者が発行します。

  1. 管理者でログイン → 管理画面 → ユーザー → 運用確認bot ユーザーの編集画面
  2. 「アプリケーションパスワード」で名前(例: cursor-ops-status-tools)を入れて追加する
  3. 表示されたパスワード(xxxx xxxx xxxx xxxx xxxx xxxx)を控える。この画面を閉じると二度と表示されません

アプリケーションパスワードは HTTPS のサイトでのみ使えます(ローカルの HTTP では wp-config.php に define( 'WP_ENVIRONMENT_TYPE', 'local' ); が必要)。

3. 失効させる ​

bot をやめるときは、管理者が同じ画面で該当のアプリケーションパスワードを「取り消す」。

4. 漏れた疑いがあるとき ​

運用確認bot は上記の制限により、漏れたパスワードでプロフィールを変えたりアプリケーションパスワードを追加発行したりはできません。影響は上の表の「できる」の読み取りに限られます。それでも念のため、次のどちらかを行ってください。

  • アプリケーションパスワードをすべて取り消し、ログインパスワードもリセットする(ロールを付け替えた・他のロールを足した場合など、制限が外れていた期間があり得るため)
  • 運用確認bot ユーザーを削除して作り直す(確実)

この制限がかかるのは ops_status_reader だけを持つユーザーです。他のロールを足すと外れるため、兼用しないでください。

設定(Cursor 側) ​

  1. .cursor/mcp.json.example を .cursor/mcp.json にコピーする(.cursor/mcp.json は gitignore。パスワードをコミットしない)
  2. ops-status-tools の env を書き換える
変数必須説明
WP_SITE_URLはいWordPress のサイト URL。https:// 必須(http:// は localhost / 127.0.0.1 / [::1] / *.local / *.test のみ)。リダイレクトは追わないので、リダイレクト先の URL(www の有無も含む)を書く
OPS_STATUS_WP_USERNAMEはい運用確認bot ユーザーのユーザー名
OPS_STATUS_WP_APP_PASSWORDはい運用確認bot ユーザーのアプリケーションパスワード(スペース込みで可)

新台情報担当 MCP(NEW_MACHINE_WP_*)や有料記事用の .env.local(WP_USERNAME / WP_APP_PASSWORD)とは別の変数名です。資格情報を混ぜないでください。

json
{
  "mcpServers": {
    "ops-status-tools": {
      "command": "node",
      "args": ["scripts/mcp-ops-status-tools.mjs"],
      "env": {
        "WP_SITE_URL": "https://example.com",
        "OPS_STATUS_WP_USERNAME": "ops-status-bot",
        "OPS_STATUS_WP_APP_PASSWORD": "xxxx xxxx xxxx xxxx xxxx xxxx"
      }
    }
  }
}

設定変更後は Cursor を再読み込みし、MCP ops-status-tools が有効になっていることを確認します。リポジトリで npm install 済み(@modelcontextprotocol/sdk)であることが前提です。

利用可能な Tool ​

MCP Tool name主な引数REST
ops_status_summary任意 date(Y-m-d)GET /ops-status/v1/summary
ops_status_daily_articlesdate_from, date_to(最大 31 日)GET /ops-status/v1/daily-articles
ops_status_daily_articleid, 任意 include_bodyGET /ops-status/v1/daily-articles/{id}
ops_status_importsなしGET /ops-status/v1/imports
ops_status_new_machineなしGET /ops-status/v1/new-machine
ops_status_birthdayなしGET /ops-status/v1/birthday
ops_status_pworld_mails任意 date(Y-m-d)GET /ops-status/v1/pworld-mails

戻り値は REST のレスポンス JSON そのままです。HTTP エラー・通信失敗・設定不足のときは isError: true で {"error":"...","status":403,"data":{...}} のように返します。入出力とエラー条件の正本は API-006 です。

日次チェックの流れ ​

  1. ops_status_summary(引数なし)で今日と前日の状態(おすすめ案は今日と明日)をまとめて取る
  2. daily_articles.missing_dates に日付があれば、その日の日別記事が無い
  3. daily_articles.items[].status が draft / pending のままの記事と、considerations で filled: false の欄を確認する
  4. imports.latest_days[].latest_day が前日になっていないホールがあれば、取込が済んでいない。missing_dates に日付があれば、昨日までの直近 14 日のうちその日の db2023 が欠けている。定休日・臨時休業日も欠けた日として出るので、人間が休業と確認済みの日は報告しない
  5. new_machine.last_run.failed_sites が空でない、または unlinked_count が増えていれば人間に報告する
  6. recommendation_drafts[] で今日と明日(target_date)のおすすめ案の有無(id)と status を確認する。明日の案が draft のままなら管理画面(ADM-037)での承認待ちなので人間に知らせる
  7. 考察の中身を確認したいときだけ ops_status_daily_article に include_body: true を付ける
  8. ops_status_birthday の upcoming_unlinked_count が 0 でなければ、誕生日紐付け担当(mcp-birthday-tools)に紐付けを頼む
  9. 22:30 の取込より後に ops_status_pworld_mails に翌日の date を渡し、items[].displayed が true の行があるのに mail_image_cache[].state が empty のままなら人間に報告する(記事のメール欄が「画像なし」のまま。Issue #4051)

1 ユーザーあたり 1 分 120 回までです。超えると 429 になるので、ループで叩かず ops_status_summary を使ってください。

REST の例(curl) ​

bash
SITE=https://example.com
AUTH='ops-status-bot:xxxx xxxx xxxx xxxx xxxx xxxx'

# 今日(サイトのタイムゾーン)と前日のまとめ
curl -sS -u "$AUTH" "$SITE/wp-json/ops-status/v1/summary"

# 期間の日別記事
curl -sS -u "$AUTH" "$SITE/wp-json/ops-status/v1/daily-articles?date_from=2026-10-01&date_to=2026-10-03"

# 1 件(考察本文つき)
curl -sS -u "$AUTH" "$SITE/wp-json/ops-status/v1/daily-articles/123?include_body=1"

トラブルシューティング ​

症状確認
WP_SITE_URL / OPS_STATUS_WP_USERNAME / ... を設定.cursor/mcp.json の ops-status-tools.env
HTTP 401(incorrect_password / invalid_username)ユーザー名・アプリケーションパスワードの誤り、取り消し済み、HTTP サイトでの利用
HTTP 403(rest_forbidden、権限がありません)認証ヘッダーが PHP に届いていない、または権限グループが「運用確認bot」でない・ADM-035 で「運用状態の確認」が外されている
HTTP 4291 分 120 回を超えた。1 分待つ
リダイレクトされましたWP_SITE_URL を location の URL(https / www の有無)に合わせる
HTTP 404(rest_no_route)テーマが本機能を含むバージョンか。パーマリンク設定が「基本」だと /wp-json/ が使えない場合がある
JSON 以外の応答WAF・メンテナンス画面・PHP エラー。body の先頭を確認

403 の切り分けは 新台情報担当 MCP の「403 の切り分け」 と同じ手順(/wp/v2/users/me で認証できているかを見る)です。

実装メモ ​

  • 本体: scripts/mcp-ops-status-tools.mjs(テスト: npm run test:mcp-ops-status。npm test にも含まれる)
  • 期間の上限 31 日は OpsStatusRestController::MAX_RANGE_DAYS と同期する
  • 権限判定とレート制限は REST 側(WordPressOpsStatusPermissionChecker)。MCP 側では判定しない