ghost-inspector-mcp について
ghost-inspector-mcp は、Ghost Inspector の E2E ブラウザーテストを調査・診断・管理するツールを AI エージェントに提供します。複雑なテスト環境向けに、失敗分析やテスト品質の確認を行い、変更や実行には明示的な許可と安全策を設けています。
主な機能
- 01アカウントのフォルダー、スイート、テストを一覧
- 02古い失敗と実際の不具合を区別
- 03モジュール依存関係と影響範囲を確認
- 04動作を検証していないテストを特定
- 05修正案を作成しテスト実行をプレビュー
- 06許可制でテストを更新・移動・実行
活用シーン
- 01失敗テストと失敗ステップを診断
- 02共有モジュールの変更による影響を確認
- 03アサーションのない合格テストを特定
- 04変更を適用する前にテスト定義を検証
MCP 対応
MCP サーバーは Ghost Inspector API を使い、テストの読み取り、診断、検証、書き込み、実行ツールを公開します。書き込みと実行には別々の環境変数による許可が必要で、削除機能はありません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y ghost-inspector-mcpGHOST_INSPECTOR_API_KEYシークレットYour personal Ghost Inspector key, from Account Settings then API Access. Read fresh on every call, never written to disk, never echoed back.GHOST_INSPECTOR_ORG_IDOrganization id. Needed only to execute a validation; read it from gi_whoami.GHOST_INSPECTOR_ALLOW_WRITESSet to exactly true to let the five write tools act. They are listed either way; anything else keeps the server read-only.GHOST_INSPECTOR_ALLOW_RUNSSet to "true" to let gi_run_test execute a stored test against a real environment, which can submit a real form. Deliberately not implied by GHOST_INSPECTOR_ALLOW_WRITES: an edit can be rolled back from the backup this server returns, a submission cannot. Defaults to false.GHOST_INSPECTOR_BACKUP_DIRWhere the write path saves the prior definition of every test it touches, credentials removed. Defaults to ~/.ghost-inspector-mcp/backups, created owner-only.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
22掲載時のツール一覧 · 2 週間前に更新
このツールにパラメーターはありません。
詳細
ghost-inspector-mcp
Ghost Inspector API 用の MCP サーバーです。Web UI をクリックして操作する代わりに、Claude、OpenAI、OpenCode、独自の自動化など、普段使用しているエージェントからエンドツーエンドのブラウザーテストを操作できます。
ステータス
ツールは 20 個あります。14 個は読み取り専用、5 個は書き込みを行い、1 個は実際にテストを実行します。すべてのツールが常に一覧に表示されます。利用を許可する設定がない場合、制限付きのツールは非表示になるのではなく、呼び出しを拒否します。そのため、ツールが表示されない理由を推測する必要はありません。
この表は、ツール全体を把握するための一覧です。各ツールの詳細や注意点は、エージェントが実際に読むツール自身の説明に記載されています。
アカウントを把握する
| ツール | アクセス | 機能 |
|---|---|---|
gi_whoami | 読み取り | API キーを検証し、アクセス可能な組織とその ID を一覧表示して、どの利用制限が解除されているかを報告します。設定に問題がある場合や、エージェントからこのサーバーでは何も変更できないと言われた場合は、ここから始めてください。 |
gi_inventory | 読み取り | アカウント全体をフォルダー → スイートのツリー形式で表示し、スイートごとに成功/失敗/モジュール/未実行のテスト数と、失敗したテストの ID と名前を示します。フォルダーで絞り込むか、失敗したスイートのみを指定できます。 |
gi_find_tests | 読み取り | 名前、フォルダー、スイート、またはテスト自身のステップの内容(コマンド、フォールバックセレクター、値)でテストを検索し、他のすべてのツールで使用する ID を返します。 |
gi_module_usage | 読み取り | execute ステップの逆引きインデックスです。インポートされた各テストについて、直接インポートしているテストと、推移的な影響範囲全体を ID とともに表示します。また、どこからもインポートされていないモジュール、インポート専用フラグが設定されていないインポート済みテスト、参照切れ、循環も検出します。一覧はフォルダーまたはスイートで絞り込めますが、影響範囲はアカウント全体が対象です。テストごとに 1 回のリクエストを行います。 |
gi_get_test | 読み取り | 1 つのテストについて、保存済みの定義、識別情報、状態を取得します。編集時の同時実行トークンとして gi_update_test が必要とする dateUpdated も含まれます。編集内容を作成する前に呼び出してください。一度に最大 20 件まで取得できます。expandModules を指定すると、実行時の内容をステップごとに、その所有元とともにインライン展開します。 |
問題を特定する
| ツール | アクセス | 機能 |
|---|---|---|
gi_stale_tests | 読み取り | テスト全体の execute チェーンにある dateUpdated を各テストの最終実行日時と比較し、失敗したテストを古い結果によるものと実際の不具合に分類します。また、変更より前の結果で成功しているテストも検出します。フォルダーまたはスイートで絞り込めます。テストごとに 1 回のリクエストを行います。 |
gi_vacuous_tests | 読み取り | 成功していても何も証明していないテストを、3 つの種類に分けて検出します。ステップを 1 つも実行しないテスト、ステップは実行するもののアサーションが一切ないテスト、テストが何かを行う前から真だった可能性がある最後のアサーションだけを含むテストです。フォルダーまたはスイートで絞り込めます。 |
gi_test_result | 読み取り | 1 つのテストが失敗した理由を示します。失敗したステップ、そのエラー、実際に解決されたセレクターだけではなく、テストに記述されていたセレクター、さらにそのステップを実際に所有するテストまたはモジュールを返します。推測は行わず、現在の定義と位置を照合します。結果が変更より前のものであれば証拠にならないため、まず古さの判定を示します。実行時のスクリーンショット、動画、URL、コンソールも返します。一度に最大 20 件まで取得できます。 |
gi_test_history | 読み取り | あるテストの実行履歴を新しい順に最大 500 件表示します。各判定と失敗したステップ、最後に成功した実行、現在の連続失敗が始まった最初の実行が含まれます。どこまでさかのぼって確認できたかも示します。 |
gi_failure_groups | 読み取り | スイートやフォルダーをまたいで、失敗し始めた時期ごとに失敗テストをグループ化し、共通するエラーと対象を示します。数時間以内に多数のテストが失敗している場合、通常は共通の原因があります。 |
修正する
| ツール | アクセス | 機能 |
|---|---|---|
gi_propose_repair | 読み取り | 診断を具体的な提案に変換します。書き換え後のステップ、そのステップを所有するテスト、書き込みに使用するトークンを提示します。変更は適用せず、診断が古い場合やステップを特定できない場合は拒否します。 |
gi_plan_test | 読み取り | gi_validate_test が送信する内容をそのまま表示します。モジュールをインライン化し、{{variables}} を解決し、送信を防ぐ3層のガードをすべて適用したうえで、拒否されるかどうかを示します。ブラウザーは起動せず、組織 ID も必要ありません。 |
gi_validate_test | 読み取り¹ | 定義をオンデマンド実行にかけます。実行しますが、その結果は破棄し、すべてのステップを報告します。スイートの設定と変数を再現し、3層のガードで送信を防ぎます(安全性モデルを参照)。 |
gi_screenshot_status | 読み取り | テストのスクリーンショット比較を表示します。適用中の設定(テストで未設定の場合はスイートから継承)、しきい値と比較した差分、比較対象の画像、次回の実行で使用されるベースラインを示します。ベースラインは承認直後には異なります。一度に最大20件まで指定できます。 |
gi_screenshot_diff | 読み取り | スクリーンショットの変更箇所を示します。結果のフルサイズ画像とベースラインをピクセル単位で比較し、変更された帯状の領域と、差分が大きい箇所のフルサイズの切り抜きを返します。表示順はベースライン、現在の画像です。 |
gi_update_test | 書き込み | 4つのガードと同時実行トークンを使って、テストのステップを置き換えたり、名前を変更したり、開始 URL を変更したりします。変更前の定義は所有者専用ファイルに保存されます。 |
gi_move_suite | 書き込み | テストを含むスイートを別のフォルダーに移動します。元に戻せるよう、以前のフォルダーを返すため、取り消しは1回の呼び出しで済みます。 |
gi_move_test | 書き込み | 1つのテストを別のスイートに移動します。テストの廃止にも使用します。元に戻せるほか、移動先でスケジュール実行されるかどうかも示します。移動先ではテストが実行されるようになるためです。 |
gi_create_suite | 書き込み | 空のスイートを作成します。フォルダー名を指定すれば、そのフォルダー内に作成します。同じ名前の兄弟スイートがある場合、明示的に指定しない限り拒否します。 |
gi_duplicate_test | 書き込み | テストをコピーしてスイートに配置し、名前を変更し、必要に応じて開始 URL も1回の呼び出しで変更します。新しいテストを作成する唯一の方法です。Ghost Inspector には作成用エンドポイントがないため、コピー元のテストが必要です。デフォルトでは、コピーしたテストのスケジュールはクリアされます。 |
gi_accept_screenshot | 書き込み | 最新のスクリーンショットを新しいベースラインにします。ただし、確認した結果そのものであり、依然として最新かつ完了済みで、比較が失敗している場合に限ります。API ではベースラインを復元できないため、置き換えたベースラインを返します。 |
gi_run_test | 実行 | 保存されたとおりにテストを実行し、判定が出るまで待機します。書き込みとは別の独自のゲートを設けています。フォームを送信するテストは、呼び出し時に確認しない限り拒否されます。 |
¹ gi_validate_test は何も保存しませんが、実際の URL に対して実際のブラウザーを操作するため、読み取り専用とは表示されません。
6つの書き込みツールは、GHOST_INSPECTOR_ALLOW_WRITES が正確に true でない限り拒否します。gi_run_test は、GHOST_INSPECTOR_ALLOW_RUNS が正確に true でない限り拒否します。拒否されても何も変更されず、設定すべき変数が示されます。gi_whoami は両方のゲートを報告します。
意図的に含めていない機能:あらゆる種類の削除。 DELETE /suites/{id}/ は取り消しができず、スイート内のすべてのテストを連鎖的に削除します。この影響範囲の大きさはエージェントに任せるべきではありません。同じ理由から、復元に使えるバージョン履歴がないテストの削除も含めていません。
何もない状態からテストを作成することはできません。 Ghost Inspector には作成用エンドポイントがありません。POST /tests/ はテスト一覧を返し、組織やフォルダーを対象とするバリエーションは404を返します。また、ベンダーのドキュメントには更新、複製、削除のみが記載されており、作成はありません。サポートされている方法は gi_duplicate_test です。既存のテストをコピーし、配置して、名前を変更します。コピー元が必要であることについて誤解を招かないよう、機能に即した名前になっています。
リグレッションが最後に成功した実行までをたどるには、gi_test_history を使います。古い結果は削除されるため、回答には必ず調査範囲が示されます。どこまでさかのぼったのか、そしてそれが Ghost Inspector に保存されている履歴の末尾なのか、指定された範囲の末尾にすぎないのかが分かります。
質問できること
ツールではなく、エージェントに話しかけます。サーバーは次のような質問に答えるために作られています。
- 「失敗しているテストのうち、本当に壊れているものと、誰かが編集してから実行されていないだけのものはどれですか?」 ― ダッシュボードでは判別できない違いであり、トリアージセッションがたいていここから始まる理由です。
- 「チェックアウトのテストが失敗するのはなぜですか?」 ― 失敗したステップ、そのエラー、そしてどのテストまたはモジュールが該当するかを確認できます。
- 「この共有モジュールを変更したら、何が壊れますか?」 ― 直接のインポート元と、推移的な依存関係全体を確認できます。通常、影響範囲はかなり広くなります。
- 「成功しているテストのうち、実際には何も検証していないものはどれですか?」 ― テストが何も証明していないのに成功する、3つの異なるケースを確認できます。
- 「そのセレクターを修正して。」 ― 変更案を提示し、保存せずに実行して解決することを確認したうえで、ガードのもとで適用し、最後にテストを実行して確認します。各ステップは個別のツールで、変更や実行を伴うものは、事前にユーザーの許可が必要です。
規模について。 このサーバーが力を発揮するのは、テストが何百件も蓄積し、共有モジュールの所有者が不明確で、何カ月もトリアージされていない失敗テストの一覧があるような、整理が行き届いていないアカウントです。小規模で適切に管理されたアカウント――テストが数十件で、モジュールがなく、すべて成功している場合――では、gi_stale_tests、gi_module_usage、gi_vacuous_tests が何も返さないのが正しく、サーバーがほとんど何もしないように見えるでしょう。それはそのアカウントに対する正直な答えであり、故障ではありません。
これが存在する理由
Ghost Inspector の API は小さく安定しているため、1 対 1 のラッパーを作っても curl 以上のものは得られません。このサーバーが提供するのは、curl ではできない次の 3 つです。
- API が提供しない集計 — アカウントをフォルダー → スイートのツリーとして、正確な件数とともに表示すること、各モジュールをインポートしているテストの逆引きインデックス、そして失敗したテストを本当に壊れているものと単に古くなっているものに分けることです。
- 書き込み時のガードレール — テストステップにはバージョン履歴がなく、リサイクルビンもありません。上書きは取り消せません。
- 呼び出し元のモデルに、問題を起こさない方法を教えるツールの説明 — 蓄積された注意点をツールに含めることで、すべてのエージェントが高くつく失敗から学ぶことなく、すぐに活用できます。
この API を扱うコミュニティ製のラッパーはほかにもあります。ここで異なるのは、その設計方針です。オプトインするまでは何も書き込まず、実行せず、どのオプトイン段階でも削除は行わず、すべての書き込みに無効化できないガードを設けています。
この 3 つ目の点が核心なので、具体例を 2 つ紹介します。
テストを Import Only にすると、Ghost Inspector では「このテストはモジュールであり、ほかのテストがそのステップをインポートする」という意味になりますが、保存済みの結果が削除されます。そのため、すべてのモジュールは恒久的に「未実行」になります。結果はなく、passing はブール値ではなく、最終実行日は 1970-01-01 のエポックセンチネルに固定されます。古いテストを検出する単純な実装では最終実行日で並べ替えるため、アカウント内のすべてのモジュールが、最も古く、最も壊れているものとして報告され、稼働中のすべてのテストが共有しているステップを削除するよう勧めてしまいます。このサーバーはそのことを理解し、それを防ぐ判定条件を備えています。
また、ステップがすべて、ステップのないモジュールを呼び出す execute だけのテストは、実行するステップが 0 個で合格します。失敗するものが何もないからです。ダッシュボードでは何も検証していないのに緑色で表示されます。緑色は誰も調査しないため、赤色よりも厄介です。共有モジュールを 1 つ空にすると、それをインポートしているすべてのテストで、この状態が一斉に、しかも気づかれないまま発生します。
これは、テストが中身を失う 3 つのパターンのうち、最も小規模なものです。数百件のテストがある実際のアカウントで gi_vacuous_tests を実行したところ、最も大きなグループはこのパターンではなく、すべてのステップを実行するものの、アサーションを一切含まないテストでした。ステップでエラーが起きた場合にしか失敗しません。3 つ目のグループは最後のステップでしかアサーションを行わず、そのステップに到達する前から成立していた可能性があります。いずれも緑色です。
インストール
Node 18 以降が必要です。事前にインストールするものはありません。MCP クライアントが次のコマンドでサーバーを起動します。
npx -y ghost-inspector-mcp
これにより、常に最新リリースが実行されます。チームで設定を共有する場合はバージョンを固定するのがおすすめです。その場合は、バージョンを指定します。npx -y [email protected]
この 2 つは API キーの入力を求め、設定ファイルではなく VS Code 独自のシークレット入力に保存します。
サーバー自体を開発する場合は、代わりにクローンしてビルドします。
git clone https://github.com/charliemtnez/ghost-inspector-mcp.git
cd ghost-inspector-mcp
npm install && npm run build
設定
個人用 API キーを取得します:Ghost Inspector → 右上の名前にカーソルを合わせる → Account Settings → API Access。キーはユーザーごとに発行され、再生成すると以前のキーは直ちに無効になります。
| 変数 | 必須 | 用途 |
|---|---|---|
GHOST_INSPECTOR_API_KEY | はい | 個人用キー |
GHOST_INSPECTOR_ORG_ID | 検証を実行する場合 | 組織 ID — gi_whoami で確認できます。gi_plan_test には不要です |
GHOST_INSPECTOR_ALLOW_WRITES | いいえ(デフォルトは false) | true に設定すると、6 つの書き込みツールを実行できるようになります。どちらの場合もツールは表示されます |
GHOST_INSPECTOR_ALLOW_RUNS | いいえ(デフォルトは false) | true に設定すると、gi_run_test を実行できるようになります。ALLOW_WRITES からは有効になりません — 編集はこのサーバーが返すバックアップからロールバックできますが、送信済みのフォームはロールバックできません |
GHOST_INSPECTOR_BACKUP_DIR | いいえ(デフォルトは ~/.ghost-inspector-mcp/backups) | 書き込み処理で、変更対象の各テストの変更前の定義を保存する場所です。macOS と Linux では所有者のみがアクセスできる状態で作成されます。Windows ではユーザープロファイルの権限を引き継ぎます |
設定には環境変数のみを使用します。.env は意図的にサポートしていません。これはプロジェクトディレクトリを持たないグローバルコマンドとして配布されており、シークレットを置く場所がもう 1 つ増えることは、漏えいする場所がもう 1 つ増えることになるためです。キーは呼び出しごとに再読み込みされるため、再起動せずにローテーションが反映されます。
Claude Code
claude mcp add ghost-inspector --scope user -- npx -y ghost-inspector-mcp
ネイティブの Windows(WSL ではない環境)では、npx は .cmd スクリプトであり、シェルを介さずにプログラムを起動するクライアントからは実行できません。cmd 経由であれば、どちらの環境でも動作します。
claude mcp add ghost-inspector --scope user -- cmd /c npx -y ghost-inspector-mcp
Claude Desktop、Cursor、Windsurf、および JSON 設定を受け付けるその他のクライアント
{
"mcpServers": {
"ghost-inspector": {
"command": "npx",
"args": ["-y", "ghost-inspector-mcp"]
}
}
}
ネイティブの Windows でサーバーが起動しない場合(spawn npx ENOENT または EINVAL)、"command": "cmd" と "args": ["/c", "npx", "-y", "ghost-inspector-mcp"] を使用してください。
env ブロックは不要です。サーバーはクライアントを起動したプロセスの環境を引き継ぐため、シェルプロファイルでキーをエクスポートすれば十分であり、設定ファイルにキーを置く必要もありません。クライアントが環境を引き継げない場合にのみ追加してください。
その他の MCP クライアント
stdio 経由で npx -y ghost-inspector-mcp を指定するか、クローンから node <path>/dist/index.js を実行し、キーを環境変数として渡してください。
ツールは表示されるものの、すべての呼び出しでキーがないと表示される場合
クライアントは、ほぼ間違いなくターミナルではなく、デスクトップアイコン、Spotlight、またはランチャーから起動されています。これらはログインシェルを実行しないため、~/.zprofile と ~/.bash_profile は読み込まれず、export も実行されません。その結果、サーバーは正常に起動してツールを登録するものの、環境変数からキーを取得できません。
クライアントをターミナルから起動するか、起動時にサーバー自身がキーを読み込むようにしてください。
claude mcp add ghost-inspector --scope user -- \
sh -c 'GHOST_INSPECTOR_API_KEY="$(cat ~/.gi-key)" exec npx -y ghost-inspector-mcp'
同じラッパーは、JSON 設定で "command": "sh" と "args": ["-c", "..."] を指定しても使用できます。キーはユーザーのみが読み取れる 600 のファイルに保存され、クライアントの設定に含まれることはありません。
Windows ではこの問題は発生しません。ユーザー環境変数は設定後に起動するすべてのプログラムに引き継がれ、デスクトップショートカットも対象です。注意が必要なのは、すでに起動しているクライアントは古い環境変数を保持する点です。システムトレイからも含めて完全に終了し、再起動してください。
API キーの取り扱い
Ghost Inspector はクエリ文字列の ?apiKey= で認証するため、慎重に扱わないと認証情報がシェルの履歴、プロキシログ、AI との会話の記録に残ります。
# In a terminal you will close afterwards — the value never enters the
# command, so it never enters your history.
umask 077
read -rs 'GI?Ghost Inspector API key: '; printf '%s' "$GI" > ~/.gi-key; unset GI
# Then, in your shell profile:
export GHOST_INSPECTOR_API_KEY="$(cat ~/.gi-key)"
echo ではなく printf を使うことが重要です。末尾の改行がクエリパラメーター内のキーを破損させます。
Windows の場合は、PowerShell でユーザー環境変数として保存してください。
# Read-Host hides what you type, and PowerShell's history records only this
# line, never the key itself.
$k = Read-Host 'Ghost Inspector API key' -AsSecureString
[Environment]::SetEnvironmentVariable('GHOST_INSPECTOR_API_KEY', [Net.NetworkCredential]::new('', $k).Password, 'User')
Remove-Variable k
キーはユーザーアカウントのレジストリ設定(HKCU\Environment)に保存されます。読み取れるのは自分とマシンの管理者であり、ホームディレクトリ内の 600 ファイルと同じ信頼レベルです。その後、MCP クライアントを再起動してください。上の表にあるほかの変数も同じ方法で設定できます。例:[Environment]::SetEnvironmentVariable('GHOST_INSPECTOR_ALLOW_WRITES', 'true', 'User')
このサーバーは、次のことを決して行いません。
- ツール呼び出しを通じてキーを尋ねること(会話の記録に秘密情報が残ってしまいます)
- キーをディスクに書き込むこと
- ログ行、エラーメッセージ、ツールの応答にキーを含めること
安全モデル
明示的に許可しない限り、何も書き込まれず、実行もされません。 変更を伴うツールが動作するのは GHOST_INSPECTOR_ALLOW_WRITES=true の場合のみで、gi_run_test が動作するのは GHOST_INSPECTOR_ALLOW_RUNS=true の場合のみです。これらが設定されていなければ、エージェントに何を頼んでも変更や実行はできません。チェックはハンドラー内で行われるため、呼び出し元が何を送信してもこの制限は有効です。すべてのツールは MCP アノテーション(readOnlyHint、destructiveHint)も宣言するため、それらに基づいて権限を制御するクライアントにも、サーバーが適用するのと同じ安全対策が認識されます。これには、実際の URL に対して実際のブラウザーを操作することは、何も保存しなくても副作用となるため、gi_validate_test が読み取り専用としてマークされていないことも含まれます。
隠さず、ゲートで制御します。 ゲートが開いているかどうかにかかわらず、すべてのツールが一覧に表示され、権限チェックはツールの呼び出し時に実行されます。一覧から除外されたツールは、存在しないツールと見分けがつきません。そのため、短い一覧を見たエージェントはその機能がないと判断し、そう伝えてしまいますが、それを訂正する手段はありません。ここでは、ゲートで制御された呼び出しは拒否され、何にも触れず、設定すべき変数を示します。
表示されていることは、権限があることを意味しません。この2つは意図的に分けられています。一覧はこのサーバーに何ができるかをエージェントに伝え、ゲートは今その操作を許可するかどうかを決定します。
設計上、スイートの削除機能は公開していません。 DELETE /suites/{id}/ はスイート内のすべてのテストに連鎖的に適用され、バージョン履歴もごみ箱もありません。この操作は、何をしているか理解している人が意図的に curl を実行する場合に限られます。
失敗したリクエストは再試行されません。 タイムアウトや接続の切断は、再試行されずにエラーとして表面化します。これは見落としではなく、意図的な判断です。execute と書き込みエンドポイントは冪等ではありません。ブラウザーテストを気付かないうちに2回実行したり、最初の試行が実際には成功していた書き込みを再適用したりする再試行は、このサーバーが防ごうとしているまさにその種の予期せぬ事態を招く代わりに、利便性を得ることになります。読み取り専用の呼び出しは安全に再試行できるため、エージェントにもう一度尋ねるだけで済みます。
書き込みにはガードが設けられています。 テストの更新では次の4つを順番に実行し、どれも無効にはできません。
dateUpdatedをexecuteチェーン全体にわたって前回の実行時と比較します。モジュールが前回の実行後に編集されている赤判定のテストは、壊れているのではなく、古くなっています。その失敗をもとに診断した修正は、もはや存在しないバージョンを対象とした診断です。インポートは最大 10 階層までネストするため、探索には上限があり、循環も検出できます。実際のアカウントでは、ダッシュボード上で 1 年以上赤判定のままになっていたテストについて、最終実行の数週間後に定義が編集されていたため、修正を拒否しました。- 拒否する場合も含め、変更前の定義全体を
GHOST_INSPECTOR_BACKUP_DIR配下の所有者専用ファイルに保存し(ディレクトリは 700、ファイルは 600、認証情報は削除)、そのパスと概要を返します。Ghost Inspector はステップのバージョン履歴を保持しないため、このファイルがロールバック手段そのものです。verbose: trueを指定するとファイルの内容もインラインで返され、ファイルを書き込めなかった場合もインラインで返されます。 - 変更を適用します。
- 送信した内容が正確に反映されたこと(各ステップの
sequenceとしての位置、名前、開始 URL)と、送信していないフィールドがすべて変更されていないことを再読み込みして 2 回照合します。HTTP 200だけでは、どちらも証明できません。
書き込みレスポンスにはレコードの新しい dateUpdated が毎回含まれるため、連続して編集する場合も、その都度再読み込みする必要はありません。
保存された認証情報がエージェントに渡ることはありません。 テストとスイートのレコードには、HTTP ベーシック認証のユーザー名とパスワードがプレーンテキストで含まれます。すべてのツール結果から、認証情報に該当するキーを削除してから返します。また、検証レポートでは非公開の変数値をマスクします。
書き込みには同時実行制御トークンも必要です。 現在の値として認識している dateUpdated を指定し、レコードがその後変更されていれば書き込みを拒否します。確認フラグなら、説得されたモデルが無視できてしまいますが、実際に読み取っていなければ推測できないタイムスタンプなら、それを防げます。gi_get_test は定義とともにこのトークンを返すため、レコードの読み込みは編集の妨げではなく、通常の最初の手順です。
拒否時には、真の競合を診断するために必要な現在の値を報告し、再読み込みして変更を作り直すよう指示します。現在保存されている定義に基づいていない変更を再送すると、その定義に置き換わった内容を上書きしてしまいます。
このトークンで狭められるのは競合の発生しうる時間枠であり、完全に閉じるわけではありません。Ghost Inspector には compare-and-swap がないため、クライアント側で読み取り後に書き込みを行います。どちらかが書き込む前に両方の書き手が読み取った場合、どちらも検査を通過します。数分前や数日前に読み取ったコピーに基づいて操作するという現実的なケースは検出できますが、真の競合は検出できません。
4 つのガードはすべて、実際のアカウントで、一時的なクローンを作成、編集、削除して検証しました。検証後、アカウントはバイト単位で完全に元の状態に戻っています。0.3.0 で追加された、開始 URL の変更、保存されたステップ位置、バックアップファイル、スクリーンショットの受け付けも、同じ方法で検証しました。実環境でしか判明しない動作が 1 つあります。Ghost Inspector は書き込み時にステップを正規化し、呼び出し元が省略したフィールドを補完します。そのため、比較の前に両側を正規化します。これを行わないと、正常に反映されたすべての書き込みで、検証時に差異が報告されます。
保存済みテストの実行には、別途ゲートがあります。 gi_run_test は、何も切り詰めず、保存されたとおりのテストを実行する唯一のツールです。そのため、ほとんどのアカウントでは本番環境に対して送信します。実行には GHOST_INSPECTOR_ALLOW_RUNS=true が必要で、ALLOW_WRITES を設定しても有効にはなりません。編集なら書き込み処理が返すバックアップから復元できますが、送信済みのフォームは一切復元できません。さらに、送信を行うテストは、その呼び出しで確認しない限り拒否されます。ステップが execute の呼び出しだけで構成され、内部に送信処理が隠れているテストもあるため、判定前にモジュールをインライン展開します。また、チェーンを完全に展開できない場合は、送信を行うものとして扱います。
確認を求めるのは影響がある場合だけです。それが重要な点です。すべての呼び出しで必要なフラグは、呼び出し元が反射的に設定するフラグになります。実際のテストのサンプルで測定したところ、約4分の3で確認が求められ、残りは確認なしで実行されました。確認を求めたテストは、実際に送信コントロールをクリックするものでした。
検証によって送信されることはありません。 gi_validate_test はオンデマンド実行を使用し、定義を実行して破棄するため、アカウントに変更は加えられません。ただし、実際のURLに対して実際のブラウザーを操作するため、本番のテストと同じように実行され、無効にできない3つのレイヤーで保護されています。
- 本番のテストと同じように実行されます。 まずモジュールがインライン化されます。ステップが
execute呼び出しだけのテストでは、モジュール内にある送信処理が見えないためです。{{variables}}は、オンデマンド実行ではカスタム変数が無視され、未知の変数が空文字列として実行されるため、テスト、スイート、組織の変数から解決されます。値がない変数が1つでもあると、何も送信される前に実行が拒否されます。スイートのユーザーエージェント、リージョン、言語、遅延も引き継がれます。 - (A)静的チェック。 送信に似た対象への最初のクリック、Enterキーの押下、または送信やデータ送信につながる可能性があるスクリプトやステップ条件の箇所で実行を打ち切り、そのステップを同じ対象に対するアサーションに置き換えます。これにより、コントロールに到達できることも含め、処理の流れを検証しつつ、コントロールを操作せずに済みます。
- (B)ブラウザー内のチェック。 残りの各クリックの前に、プローブが解決先の要素を調べます。その要素がフォームの送信コントロールである場合、フォーム内のフィールド以外のコントロールである場合、またはまったく解決できない場合は、実行を停止します。どのセレクターパターンでも認識できない、フォーム内のariaラベル付き送信ボタンもここで検出されます。
- (C)トリップワイヤー。 すべてのステップの前に、すべてのページで、送信イベント、
form.submit()、非GETのfetchとXHR、sendBeaconをブロックして報告します。実行は停止しません。
それでも残るものは、隠さずに文書化されています。ページの最初のステップが実行される前にwindow.fetchまたはform.submitを保存したスクリプト、WebSocket、子フレーム内の処理、GETで送信されるデータ(ピクセルやページ遷移)です。ガードは停止する側に倒れるため、フォーム内でsubmitとして型指定された「続行」ボタンでも実行が停止します。送信を許可するオプションはありません。送信する場合は、意図的にcurlを使ってください。本番環境に触れるものには、まずgi_plan_testを使用してください。ブラウザーを起動せずに、インライン化・解決・ガードされたうえで実行される内容を正確に報告します。
開発
npm ci
npm run typecheck
npm test # builds first, then runs the suite
テストは263件で、テスト用の依存関係はありません。Node標準のランナーとassertを使用します。テストはカバレッジではなく、アサーションが失敗した場合に何が壊れるかに基づいて整理されているため、失敗時の名前から何を壊したかがわかります。
| ファイル | 固定される内容 |
|---|---|
config.test.js | 書き込みゲートが厳密な true で開き、1 や yes では開かないこと。キーは呼び出しごとに再読み込みされ、ローテーションが機能すること。redact がクエリパラメーターと単独で現れる文字列の両方を除去すること |
detail.test.js | 同時実行トークンが呼び出し元に渡されること。モジュールの未設定の判定を失敗として読み取らないこと。ステップが展開されずに返されるため、編集対象がそのステップを持つテストになること |
create.test.js | 呼び出し元が明示的に求めない限り、コピーは無効化されること。明示的な true 以外はすべてスケジュールをクリアすること。よく似たスイート名は、作成される前に拒否されること |
client.test.js | 真偽値として真でも true とは限らないこと。不明な日付は未実行として扱われること。逆の扱いをすると、実行中のモジュールがプルーンリストに紛れ込むためです。停滞した本文のダウンロードがリクエストのタイムアウトを超えて続かないこと |
graph.test.js | 循環が終了し、共有サブツリーの再展開を停止しても一度だけ報告されること。ノードが追加されない階層で深さが増えないこと。文書化されたネスト上限に達した場合、全体として処理できたかのように扱わず報告すること |
inventory.test.js | すべてのテストが必ずいずれか一つの分類に入ること。モジュールが失敗として数えられないこと。空のスイートも表示されること |
modules.test.js | 推移的な範囲が直接の件数を上回ること。循環は数を水増しせず、フラグとして扱われること。何も実行しないテストが見つかること |
diagnose.test.js | すべての sequence が 0 の状態で保存されたモジュールでも、失敗が失敗したステップに対応付けられること。実行されなかったステップが失敗として示されないこと。解決済みのセレクターを、テストが探している対象として扱わないこと。モジュール内の失敗したステップがモジュールを指すこと。消去済みの実行が、未実行のテストとして報告されないこと |
vacuous.test.js | どれほど空に見えても、モジュールを中身がないと判定しないこと。モジュールから継承したアサーションも数えること。最後のアサーションが一つだけの場合は非難せず、候補として挙げること。読み取れない定義は空として数えず、スキップすること |
repair.test.js | ページの内容にかかわらず成立するルールを適用すること。不安定なセレクターは名前を示すだけで、書き換えないこと。代わりのセレクターを考案するのは推測になるためです |
stale.test.js | 変更のないものを失うことなく、古い項目の一覧を分割すること。解析できない日付は変更ありとして扱うこと。モジュールを評価せず除外すること |
validate.test.js | モジュールから継承した送信を検出すること。定義を記述どおりにガードする方法では、実際のテスト 8 件中 5 件がライブフォームを送信すると測定されていたためです。インポートの条件が、インポートしたすべてのステップに適用され、破棄されないこと。条件が {statement} として引き継がれること。すべてのステップがブラウザー内ガードによって制御され、挿入されたステップによってレポート上のステップ N の位置がずれないこと。プライベート変数がレポートに渡らないこと |
run.test.js | 書き込みを許可しても実行までは許可されないこと。モジュール内に隠れた送信にも確認が必要なこと。完全に展開できなかったチェーンも送信として数えること |
writes.test.js | 古さを判定するガードにおける、不確かなケースすべての判定方向。Ghost Inspector 独自のステップのデフォルト値を差分として報告しないこと。書き込み後にのみ現れるフィールドも予期しない変更として扱うこと。すべてのステップが位置情報とともに保存されること。保存されたベーシック認証のパスワードがレスポンスに渡らないこと。バックアップファイルが所有者のみ読み取り可能であること |
guard-script.test.js | シミュレートされたページで実行する、ブラウザー内のプローブ、停止条件、トリップワイヤー。停止が記録され、後続のステップでも尊重されること。データを送信する処理がブロックされ、GET は通過すること。sessionStorage へのアクセスが拒否されても、停止されていない実行がスキップされないこと |
variables.test.js | スイート変数が開始 URL に渡されること。先行するステップで設定された変数はブラウザーに残されること。設定前に使用された変数、または値のないプライベート変数がある場合は実行が拒否されること |
results.test.js | スキップされたステップや未到達のステップを実行済みとして数えないこと。欠落している所要時間は再構築し、0 として報告しないこと。コンソール出力に上限を設け、黙って破棄しないこと |
find.test.js | ステップ検索がフォールバックセレクターに一致すること。結果に ID が含まれること |
history.test.js | ページをまたいで、連続した失敗の最初の失敗を見つけること。未完了の探索が、履歴全体を確認したと誤って報告しないこと。同時に始まった失敗をスイートをまたいでグループ化すること |
screenshots.test.js | 誰も確認していないスクリーンショットや、承認できる内容がないスクリーンショットを承認しないこと |
server.test.js | サーバーが起動してプロトコルに従い、書き込みゲートがエンドツーエンドで機能し、すべてのツールのアノテーションがコードで適用される状態を示すこと |
server.test.js は stdio 経由で実際のサーバーを起動します。登録ミスやスキーマの誤りを検出できるのは、この方法だけです。テストスイート内では API キーをどこにも設定していないため、Ghost Inspector にリクエストが送信されることはなく、どのマシンでも安全にテストを実行できます。 |
CI では Node 18、20、22、24 で一連のテストを実行します。engines で指定している最低バージョンに加え、2 つの LTS 系統と最新バージョンを対象にしています。これは、npx がユーザーの環境にすでにインストールされている Node で実行されるためです。2 つ目のジョブでは、作業ツリーだけでなく履歴全体を対象に漏えい監査を再実行します。後のコミットで漏えいを除去しても、履歴には残るためです。
明記しておきたい制限事項です。 ここに記載した API の動作は、単一のアカウント、単一のプランで実証的に確認したものです。確認するたびに同じ動作でしたが、別のプランでは異なる可能性があります。お使いのアカウントでこれと矛盾する動作があれば、ぜひイシューをお寄せください。
貢献
イシューや PR は歓迎します。ただし、これはベストエフォートで保守されています。実際の問題を解決するために作られたツールであり、サポート対象の製品ではありません。変更内容は CHANGELOG.md に記載しています。セキュリティに関わる内容は、公開イシューではなく SECURITY.md に従ってご報告ください。
コード、テスト、ドキュメント、サンプルには、組織固有のデータを含めないでください。ID、ホスト名、フォルダーやスイートの命名規則、テストデータの識別情報は含めないでください。これらはすべて呼び出し元の設定に属する情報です。https://example.com や [email protected] のような、明らかにサンプルだとわかるプレースホルダーを使用してください。
ライセンス
MIT です。詳細は LICENSE をご覧ください。
Ghost Inspector は、それぞれの所有者の商標です。このプロジェクトは同社とは無関係です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。