AdRails について
AdRails は Google Ads を管理するオープンソースのセルフホスト可能な MCP サーバーで、制約付きのキャンペーン変更を必要とする AI エージェントや運用担当者向けです。レビュー済みの目標状態ファイルとポリシー上限を分離し、実際の状態との差分を確認して、支出閾値に応じた一時停止を試みます。
主な機能
- 01キャンペーン状態と検索語句の読み取り
- 02目標状態ファイルから変更を計画
- 03ポリシー上限による書き込み検証
- 04プラン ID の要求と監査ログ記録
- 05支出閾値の確認とキャンペーン停止の試行
活用シーン
- 01エージェントによる状態と検索語句の確認
- 02予算や状態の変更を適用前にレビュー
- 03閾値を定期確認してキャンペーン停止を試行
MCP 対応
AdRails はローカルの stdio MCP サーバーとして動作し、Google Ads の読み取り、計画、適用、監視ツールを提供します。設定した認証情報で Google Ads API に直接接続し、ホスト型エンドポイントは使いません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
AdRails (adrails.dev)
広告を運用するAIエージェント向けのガードレール:オープンソースでセルフホスト可能なGoogle Ads MCP サーバーです。
ウェブサイトとドキュメント:https://adrails.dev · MCP Registry:dev.adrails/adrails · エージェント向けプレーンテキスト概要:https://adrails.dev/llms.txt
AdRailsはGoogle Ads向けのローカルMCP サーバーです。エージェントはキャンペーン、ステータス、検索語句を好きなだけ読み取れます。書き込みはすべて、ディスク上のレビュー済みの望ましい状態を記したファイルに反映し、稼働中の状態との差分を確認したうえで、AdRailsのツールからは書き込めないポリシーファイルに定められた上限をクリアする必要があります。Pythonパッケージとモジュールの名前は引き続きadsopsです。インストールと実行にはこの名前を使います。
他とは異なる点は3つあります。
- 自分のキーを使用します。 自分のマシン上で、自分のGoogle CloudプロジェクトとGoogle Ads認証情報を使って動作します。ホスティングされているものはありません。このパッケージが通信するエンドポイントはGoogle Ads APIのみで、認証情報は設定したソース(サービスアカウントのJSONファイル、静的トークン、またはシークレットマネージャーへの照会)から読み込まれます。
- 自分で上限を設定します。 上限はAdRailsのツールからは書き込めないポリシーファイルに保存されます。
require_plan_idを有効にすると、コミットごとに、そのプラン専用に発行された未使用のplan_idを指定する必要があります。また、スケジュールされたガードのハートビートが古い場合、支出へのエクスポージャーを増やす変更は拒否されます。 - 呼び出しごとにsatsで支払います。 オプションのホスト型アドオンはLightningを優先し、呼び出しごとにsatsで従量課金されます。近日公開予定です。このリリースでは、ホスト型サービスへの通信は一切ありません。
テスト
python3 -m adsops --selftest # 430 unit checks, everything mocked
python3 tests/qa_invariants.py # 200 random sequences against a simulated Google Ads account
python3 tests/qa_inputs.py # hostile policy/state/config inputs (NaN, Infinity, bad dates, bad UTF-8, ...)
python3 tests/qa_secrets.py # canary tokens injected everywhere; none may reach output or logs
QAスイートは、adsops/への書き込み権限を持たない別のエージェントが敵対的な観点から作成し、すべての指摘を修正するか、意図した動作として文書化しました。
AdRailsで保証できないこと
実際のアカウントに接続する前にお読みください。
- 自動的に一時停止を試みるしきい値であり、支出の厳格な上限ではありません。 ガードは支出額を設定した数値と比較し、一時停止操作を実行します。これは被害の抑制であり、請求の制御ではありません。
- Googleは、特定の日に1日の平均予算の最大2倍まで広告を配信する可能性があります。 1日の予算は平均であり、上限ではありません。また、一時停止は拒否されたり、反映が遅れたりする可能性のあるAPI呼び出しです。
- レポートには遅延があります。 AdRailsが読み取る支出額は、広告配信から数分から数時間遅れます。
- ガードが動作するのは、スケジュールされていて、マシンが起動している間だけです。 チャットセッションのMCPプロセスは監視機能ではありません。マシンがスリープ中はチェックが実行されず、支出は増え続け、ハートビートは古くなります。
- 同じユーザーとしてシェルにアクセスできるエージェントは、ローカルツールを迂回できます。 AdRailsが制約するのは提供するツール呼び出しであり、その下で動作するマシンではありません。必要であれば、エージェントをサンドボックス化してください。
- 不適切な除外キーワードは、良質なトラフィックを抑制する可能性があります。 ここで除外キーワードは追記のみのため、誤ったキーワードを取り消すのも容易ではありません。
- アカウントと支出については、ご自身で責任を負う必要があります。 プラットフォーム側の請求上限を、実際の上限として設定してください。
クイックスタート
1. インストールします。
# from GitHub (PyPI release coming soon)
pipx install git+https://github.com/antonioac1/adrails # console script: adsops-mcp
# or run without installing:
uvx --from git+https://github.com/antonioac1/adrails adsops-mcp --config /absolute/path/config.json
ほかに依存関係はありません。google-auth がインストールされていない場合、サービスアカウントトークンの署名にはシステムの openssl を使用します(google-auth を使いたい場合はインストールしてください)。
コア部分は標準ライブラリのみで動作します。オフラインで確認できます(すべてモックを使用し、ネットワーク接続はありません)。
python3 -m adsops --selftest # or: deploy/smoke_docker.sh
2. 設定ファイルを作成します。 すべてのアカウント、認証情報のソース、パスをここに記述します。パスの ~ は読み込み時に展開されます。
{
"tenant": "your-tenant",
"meter_log": "~/.adsops/meter.jsonl",
"audit_log": "~/.adsops/audit.jsonl",
"plan_ledger": "~/.adsops/plans.jsonl",
"lock_dir": "~/.adsops/locks",
"guard_heartbeat": "~/.adsops/guard.heartbeat",
"credentials": {"google_ads": {"type": "service_account",
"sources": [{"kind": "file", "path": "~/.adsops/sa.json"}]}},
"google_ads": {"api_version": "v24", "end_field": "end_date_time", "login_customer_id": null},
"commit_policy": {"require_clean_git": true, "allow_commit": true, "allow_set": true},
"accounts": [{"key": "main", "platform": "google_ads", "customer_id": "000-000-0000",
"campaigns": [{"key": "search_core", "state_file": "~/ads/search_core.json",
"policy_file": "~/ads/search_core.policy.json"}]}]
}
commit_policy のデフォルトは require_clean_git: true および allow_commit: false です。そのため、有効にするまではコミットと adsops_set は無効です。
3. キャンペーンのポリシーファイル(次のセクション)を作成し、両方のファイルを Git にコミットします。変更のレビューには git diff を使用します。
4. MCP クライアントにサーバーを登録します。 診断情報は stderr に出力されます。サーバーは標準入出力で JSON-RPC 2.0 を使用し、1 行につき 1 つのオブジェクトを送信します。
{
"mcpServers": {
"adrails": {
"command": "python3",
"args": ["-m", "adsops", "--config", "/absolute/path/config.json"]
}
}
}
5. ガードをスケジュールします。 チャットセッションでは支出を監視できないため、一時停止のみを行う支出チェックを、OS のスケジューラーから 15 分ごとに実行します。launchd、systemd、cron 用のテンプレートは deploy/ にあります。プレースホルダー(__PYTHON__、__CONFIG__、__PKG__、__LOGDIR__)を置き換え、インストール前に deploy/GUARD.md をお読みください。
PY=$(command -v python3); CFG=/absolute/path/config.json
PKG=/absolute/dir/containing/adsops; LOGDIR="$HOME/.adsops/logs"
mkdir -p "$LOGDIR"
sed -e "s|__PYTHON__|$PY|g" -e "s|__CONFIG__|$CFG|g" \
-e "s|__PKG__|$PKG|g" -e "s|__LOGDIR__|$LOGDIR|g" \
deploy/launchd/com.adsops.guard.plist.template \
> ~/Library/LaunchAgents/com.adsops.guard.plist
plutil -lint ~/Library/LaunchAgents/com.adsops.guard.plist
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.adsops.guard.plist
3 つのユニットが実行するコマンドはすべて PYTHONPATH=$PKG $PY -m adsops --config $CFG guard-all です。
Grok、Claude Code、Cursor、または任意の MCP クライアントから使用する
AdRails はローカルの標準入出力サーバーなので、どのクライアントでも同じコマンドを登録します。設計上、ホストされた URL はありません。
pip install git+https://github.com/antonioac1/[email protected]
# Claude Code
claude mcp add adrails -- python3 -m adsops --config /absolute/path/config.json
# Grok CLI (it also reads ~/.claude.json, .cursor/mcp.json and .mcp.json)
grok mcp add adrails -- python3 -m adsops --config /absolute/path/config.json
Cursor またはプロジェクトの .mcp.json の場合:
{"mcpServers":{"adrails":{"command":"python3","args":["-m","adsops","--config","/absolute/path/config.json"]}}}
Claude Desktop:.mcpb バンドルを最新リリースからインストールします。
詳細:https://adrails.dev/docs/mcp-clients/
ツール
| ツール | 説明 |
|---|---|
adsops_campaigns | このデプロイで操作可能なキャンペーンを一覧表示します。キー、アカウント、状態ファイル、現在有効なコミットポリシーを確認できます。 |
adsops_status | 1 つのキャンペーンの最新情報を読み取ります。ステータス、終了日、1 日の予算、本日および累計の支出、除外キーワード数、上限がポリシーファイルに由来するかどうか、ガードのハートビートの経過時間を確認できます。 |
adsops_terms | 過去 N 日間(1~90 日、デフォルトは 14 日)のクリックされた検索語句を表示します。語句、一致したキーワード、クリック数、費用を確認できます。 |
adsops_plan | 望ましい状態を記述したファイルと現在の状態との差分のみを計算します。書き込みは行いません。実行する操作、メモ、ops_count、検出した露出の増加、および有効期限付きの使い捨て plan_id を返します。 |
adsops_apply | commit=true でない限り、検証のみを行います。コミットには、commit_policy.allow_commit、Git で追跡されている状態ファイルに未コミットの変更がないこと、変更によって露出が増える場合は有効なガードのハートビート、そしてポリシーで必須の場合は adsops_plan が返した plan_id が必要です。 |
adsops_set | 短い reason を添えて、予算、ステータス、終了日、除外キーワードの変更を提案します。ポリシー上限と現在の状態を確認し、状態ファイルに書き込んで Git にコミットします。dry_run=true の場合は書き込みの代わりに plan_id を返します。ポリシーで必須の場合、apply=true にはその plan_id が必要です。 |
adsops_guard | 支出を読み取り、1 日または累計のしきい値を超えた場合はキャンペーンを一時停止します。一時停止のみで、キャンペーンの有効化、予算の引き上げ、キーワードの編集は行いません。commit=true でない限り、検証のみを行います。 |
adsops_usage | テナントの使用状況の概要を表示します。ツールごとの呼び出し数、エラー数、単位数、操作数、レイテンシの中央値を確認できます。 |
ポリシーファイル
キャンペーンごとにポリシーファイルを1つ用意し、設定の policy_file で参照します。AdRails はこのファイルを読み取るだけです。ツールが上限を書き込むことはなく、adsops_set は guards と allow_enable を明示的に拒否します。状態ファイルにも上限が含まれている場合、それらは無視されます。常にポリシーファイルが優先され、その旨は adsops_status で確認できます。
{
"customer_id": "000-000-0000",
"campaign_id": 1000000000,
"guards": {
"max_daily_budget_usd": 40,
"min_daily_budget_usd": 5,
"max_end_date": "2026-12-31",
"lifetime_spend_pause_usd": 900,
"daily_spend_pause_usd": 60,
"max_ops_per_run": 12
},
"allow_enable": false,
"max_guard_age_min": 30,
"require_plan_id": true,
"plan_ttl_s": 900
}
| フィールド | 意味 |
|---|---|
customer_id | キャンペーンが属するアカウントです。ハイフンを取り除いた後、状態ファイルと照合されます。一致しない場合は拒否されます。 |
campaign_id | このポリシーが管理する唯一のキャンペーンです。状態ファイルと完全に一致する必要があります。 |
guards.max_daily_budget_usd | 必須です。1日の予算の上限であり、プランの作成時に確認する予算上限です。 |
guards.min_daily_budget_usd | 任意です。1日の予算の下限で、最大値を超えてはなりません。 |
guards.max_end_date | 必須です。形式は YYYY-MM-DD です。プランで設定できる最も遅い終了日です。 |
guards.lifetime_spend_pause_usd | 必須です。この金額に達すると、ガードが一時停止を指示します。 |
guards.daily_spend_pause_usd | 必須です。本日の支出がこの金額に達すると、ガードが一時停止を指示します。 |
guards.max_ops_per_run | 必須の整数です。1回の実行で出力できる操作の最大数です。超過すると拒否されます。 |
allow_enable | デフォルトは false です。プランでキャンペーンを ENABLED に設定できるかどうかを指定します。 |
max_guard_age_min | デフォルトは null(チェックなし)です。設定すると、支出リスクを増やす変更は、ガードのハートビートがこの時間より新しい場合に限り許可されます。 |
require_plan_id | デフォルトは false です。true の場合、apply/commit と、apply=true を指定した adsops_set では plan_id を明示する必要があります。 |
plan_ttl_s | デフォルトは 900、範囲は 60~86400 です。発行された plan_id が使用可能な時間です。各 plan_id は1回だけ使用できます。 |
フィールドが欠落しているか不正な場合、暗黙のデフォルト値を使わず、該当フィールド名を示すエラーになります。
望ましい状態のファイル
キャンペーンごとに JSON ファイルを1つ用意し、state_file で参照します。キャンペーンの望ましい状態を記述し、差分はサーバーが計算します。
{
"customer_id": "000-000-0000",
"campaign_id": 1000000000,
"campaign_name": "Search - Core",
"status": "PAUSED",
"end_date": "2026-11-30",
"daily_budget_usd": 20,
"negatives_add": [
{"text": "free", "match_type": "BROAD"},
{"text": "cheap", "match_type": "PHRASE"}
],
"guards": {
"max_end_date": "2026-12-31",
"min_daily_budget_usd": 5,
"max_daily_budget_usd": 40,
"lifetime_spend_pause_usd": 900,
"daily_spend_pause_usd": 60,
"max_ops_per_run": 12
}
}
| フィールド | 意味 |
|---|---|
customer_id | キャンペーンが属するアカウントです。使用前にハイフンが取り除かれます。 |
campaign_id / campaign_name | このファイルが管理する唯一のキャンペーンです。どちらも実際の状態と一致しない場合、実行は中止されます。 |
status | 望ましいステータスで、ENABLED または PAUSED です。ENABLED にするには、ポリシーで allow_enable も必要です。 |
end_date | 望ましい終了日です。形式は YYYY-MM-DD で、guards.max_end_date の範囲内かつ過去の日付ではない必要があります。 |
daily_budget_usd | 望ましい1日の予算です。最小値と最大値のガード範囲内である必要があります。 |
negatives_add | {text, match_type} の追記専用リストです。マッチタイプは BROAD、PHRASE、EXACT のいずれかです。ここではキーワードを削除できません。 |
guards | キャンペーンに policy_file が設定されていない場合(レガシーモード)にのみ読み取られます。ポリシーファイルが設定されている場合、これらは無視されます。 |
これらのファイルは git に保存してください。そうすることで「レビュー済みの望ましい状態」が実現します。変更のレビューには git diff を使用し、require_clean_git によって、未コミットの編集がある場合にサーバーが処理を拒否します。
Google の公式読み取り専用 google-ads-mcp と併用
同じ MCP クライアントで両方のサーバーを並行して実行します。Google のサーバーはアドホックな GAQL の調査に応答し、書き込みは行いません。書き込み経路は AdRails のみです。エージェントは公式サーバーで読み取り、望ましい状態のファイルまたはポリシーファイルへの変更を提案し、adsops_plan / adsops_apply を通じて適用します。その間に、上限チェック、検証処理、アカウントロック、監査ログの記録が行われます。どちらも stdio 経由の JSON-RPC を使用するため、.mcp.json にそれぞれ1つずつエントリを追加するだけでセットアップは完了です。
ライセンス
Apache-2.0。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。