Appearance
運用確認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 ユーザーを作る
- 管理画面 → ユーザー → 新規追加
- ユーザー名は用途が分かる名前にする(例:
ops-status-bot)。メールアドレスは管理者が受け取れるものにする - 権限グループで「運用確認bot」を選んで追加する
- パスワードは長いランダムな値を生成したまま、控えずに追加する(ログインパスワードは使わない。bot にはアプリケーションパスワードだけを渡す)
bot ごと・用途ごとにアカウントを分けてください。 日別記事編集bot・取込担当・新台情報担当のアカウントに read_ops_status を足して兼用しないこと。編集用のアプリケーションパスワードが漏れても確認用には影響せず、その逆も同じにするためです。運用確認bot ロールの Capability は ADM-035 権限管理画面 で確認できます(既定は「運用状態の確認」のみ)。
2. アプリケーションパスワードを発行する
運用確認bot ユーザーは wp-admin を開けないため、管理者が発行します。
- 管理者でログイン → 管理画面 → ユーザー → 運用確認bot ユーザーの編集画面
- 「アプリケーションパスワード」で名前(例:
cursor-ops-status-tools)を入れて追加する - 表示されたパスワード(
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 側)
.cursor/mcp.json.exampleを.cursor/mcp.jsonにコピーする(.cursor/mcp.jsonは gitignore。パスワードをコミットしない)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_articles | date_from, date_to(最大 31 日) | GET /ops-status/v1/daily-articles |
ops_status_daily_article | id, 任意 include_body | GET /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 です。
日次チェックの流れ
ops_status_summary(引数なし)で今日と前日の状態(おすすめ案は今日と明日)をまとめて取るdaily_articles.missing_datesに日付があれば、その日の日別記事が無いdaily_articles.items[].statusがdraft/pendingのままの記事と、considerationsでfilled: falseの欄を確認するimports.latest_days[].latest_dayが前日になっていないホールがあれば、取込が済んでいない。missing_datesに日付があれば、昨日までの直近 14 日のうちその日の db2023 が欠けている。定休日・臨時休業日も欠けた日として出るので、人間が休業と確認済みの日は報告しないnew_machine.last_run.failed_sitesが空でない、またはunlinked_countが増えていれば人間に報告するrecommendation_drafts[]で今日と明日(target_date)のおすすめ案の有無(id)とstatusを確認する。明日の案がdraftのままなら管理画面(ADM-037)での承認待ちなので人間に知らせる- 考察の中身を確認したいときだけ
ops_status_daily_articleにinclude_body: trueを付ける ops_status_birthdayのupcoming_unlinked_countが 0 でなければ、誕生日紐付け担当(mcp-birthday-tools)に紐付けを頼む- 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 429 | 1 分 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 側では判定しない