mcpField
C
cdp

cdp

github.com/browser-use開発496707 回インストール8 週間前に更新
リポジトリ

cdp について

cdpは、コーディングエージェント向けのブラウザー操作スキルです。CDP全体を扱う型付きSDKとbrowser-harness-js CLIを備え、常駐セッションでChrome接続と状態を呼び出し間で再利用します。

主な機能

  1. 01CDPメソッドの型付きラッパー
  2. 02CLIからJavaScriptスニペットを実行
  3. 03常駐CDPセッションを再利用
  4. 04ブラウザータブへの接続と切り替え
  5. 05イベントの購読と待機

活用シーン

  1. 01スクリプトでページを移動・検査
  2. 02呼び出し間でブラウザーセッションを再利用
  3. 03ページやネットワークイベントの監視

インストール

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

$npx skills add https://github.com/browser-use/browser-harness-js --skill cdp

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
LICENSE
.gitignore
interaction-skills/
connection.md
dialogs.md
cookies.md
cross-origin-iframes.md
drag-and-drop.md
downloads.md
dropdowns.md
iframes.md
print-as-pdf.md
screenshots.md
network-requests.md
scrolling.md
shadow-dom.md
tabs.md
uploads.md
viewport.md
sdk/
bun.lock
browser-harness-js
gen.ts
repl.ts
package.json
session.ts
session.test.ts
js_protocol.json
tsconfig.json

詳細

CDP — browser-harness-js スキル

カスタム生成された CDP SDK(browser_protocol.json と js_protocol.json の全メソッドに型付きラッパーを用意)に加え、永続的な CDP Session を保持する小さな HTTP サーバーです。browser-harness-js CLI は初回使用時にサーバーを自動起動し、JavaScript スニペットをサーバーに転送します。

SDK はスキルの sdk/ ディレクトリにあります。このドキュメントでは、<skill-dir> は npx skills add でスキルをインストールした場所を指します(Claude Code:~/.claude/skills/cdp、Cursor:~/.cursor/skills/cdp、その他のエージェントでは異なります)。CLI は PATH 上で browser-harness-js として利用できる必要があります。

セットアップ(初回のみ)

npx skills add はエージェントのスキルディレクトリにスキルを配置しますが、CLI は PATH に追加しません。初回の呼び出し前に、CLI を利用できることを確認し、利用できない場合は PATH 上のディレクトリにシンボリックリンクを作成してください。

# macOS (Apple Silicon + Homebrew)
command -v browser-harness-js >/dev/null || ln -sf <skill-dir>/sdk/browser-harness-js /opt/homebrew/bin/browser-harness-js

# macOS (Intel) / most Linux — may need sudo
command -v browser-harness-js >/dev/null || ln -sf <skill-dir>/sdk/browser-harness-js /usr/local/bin/browser-harness-js

# Linux without sudo (ensure ~/.local/bin is on PATH)
command -v browser-harness-js >/dev/null || { mkdir -p ~/.local/bin && ln -sf <skill-dir>/sdk/browser-harness-js ~/.local/bin/browser-harness-js; }

初回実行時に bun がない場合、CLI は自動的にインストールします(サーバーは Bun ネイティブです)。オプトアウトするには BROWSER_HARNESS_SKIP_BUN_INSTALL=1 を設定してください。

使用方法

browser-harness-js '<JS>' を実行するだけです。初回の呼び出しではバックグラウンドでサーバーが起動し、以降の呼び出しでは同じプロセスに接続するため、同じ session、Chrome への同じ WebSocket、設定したグローバル変数を再利用します。

browser-harness-js 'await session.connect()'
browser-harness-js 'await session.Page.navigate({url:"https://example.com"})'
browser-harness-js '(await session.Runtime.evaluate({expression:"document.title",returnByValue:true})).result.value'

出力は生の結果コンテンツで、{ok,result} のラッパーはありません。

結果の型標準出力
文字列JSON の引用符なしのテキスト(例:Example Domain)
数値/ブール値42、true
オブジェクト/配列(空でない場合)コンパクトな JSON(例:{"frameId":"..."}、[1,2,3])
undefined/null/""/{}/[]空(出力なし)

エラーは標準エラー出力に出力され、終了コードは 1 です。CDP のエラーメッセージと JavaScript のスタックが、そのまま表示されます。例:

Error: CDP -32602: invalid params
    at _call (.../session.ts:117:33)
    ...

if browser-harness-js '...'; then ...; else handle_error; fi を使うか、$? を確認して失敗を検出してください。

標準入力から複数行のスニペットを渡す(ヒアドキュメント)。 重要:複数の文を含むスニペットでは、最後の式は自動的に返されません。return X を明示的に記述してください。最初の引数として渡す単一式のスニペットは、自動的に値が返されます。

browser-harness-js <<'EOF'
const tabs = await listPageTargets();
globalThis.tid = tabs[0].targetId;
await session.use(globalThis.tid);
return globalThis.tid;
EOF

CLI コマンド

コマンド動作
browser-harness-js '<js>'必要に応じてサーバーを自動起動し、JavaScript を評価して結果を出力します。
browser-harness-js <<EOF…EOF同じ動作をします。標準入力からコードを受け取ります。
browser-harness-js --statusヘルス情報の JSON(稼働時間、接続状態、sessionId)を出力します。停止中の場合は終了コード 1 で終了します。
browser-harness-js --start明示的に起動します(すでに起動している場合は何もしません)。
browser-harness-js --stop正常にシャットダウンします。セッションの状態は破棄されます。
browser-harness-js --restart停止して新たに起動します。
browser-harness-js --logsサーバーのログ(/tmp/browser-harness-js.log)を tail -f で表示します。

環境変数:CDP_REPL_PORT(デフォルト 9876)、CDP_REPL_LOG(デフォルト /tmp/browser-harness-js.log)。

スニペット内の API

以下のグローバル変数はあらかじめ読み込まれているため、インポートは不要です。

  • session — 永続的な Session です。すべての CDP ドメインがマウントされています:session.Page、session.DOM、session.Runtime、session.Network、……全 56 ドメイン、合計 652 メソッドです。
  • listPageTargets() — CDP の Target.getTargets を使って実際のページターゲットを一覧表示します(Chrome 144 以降でも動作します)。chrome:// および devtools:// の URL は除外されます。引数は不要で、接続済みのセッションを使用します。
  • detectBrowsers() — OS 固有のプロファイルディレクトリを検索し、リモートデバッグを有効にして実行中の Chromium ベースのブラウザーを検出します。[{name, profileDir, port, wsPath, wsUrl, mtimeMs}] を返し、起動時刻の新しい順に並べます。
  • resolveWsUrl(opts) — {wsUrl} | {port, host?} | {profileDir} から WS URL を解決します。引数なしの自動検出フローでは、代わりに session.connect() を直接呼び出してください。
  • CDP — 生成された名前空間(CDP.Page、CDP.Runtime、……)です。型名の参照に使用します。
CDP メソッドの呼び出し

すべてのメソッドは、CDP のワイヤーパラメーターに対応するオブジェクト引数を 1 つ取ります。型付きの戻り値を返します(result のラッパーや id による対応付けはありません。これらは自動的に処理されます)。

// no params
await session.DOM.enable()

// required params
await session.Page.navigate({ url: 'https://example.com' })

// all-optional params (object also optional)
await session.Page.captureScreenshot()
await session.Page.captureScreenshot({ format: 'png', quality: 80 })

// returns are stripped to the typed shape
const { root } = await session.DOM.getDocument()
const { nodeId } = await session.DOM.querySelector({ nodeId: root.nodeId, selector: 'h1' })
接続

デフォルトでは、引数なしで session.connect() を呼び出すだけです。 OS ごとのプロファイルディレクトリをスキャンして DevToolsActivePort ファイルを探し、最後に起動したものから順に、WebSocket 接続を受け付ける最初のブラウザーを選択することで、実行中の Chromium ベースのブラウザー(Chrome、Chromium、Edge、Brave、Arc、Vivaldi、Opera、Comet、Canary)を自動検出します。OS を問わず、macOS、Linux、Windows で動作します。

await session.connect()   // auto-detect

接続前に利用可能なブラウザーを確認したい場合(またはユーザーに選択してもらう場合)は、先に detectBrowsers() を使います。

const found = await detectBrowsers()
// [{ name: 'Google Chrome', profileDir, port, wsPath, wsUrl, mtimeMs }, ...]

明示的な指定方法 — 自動検出で誤ったブラウザーが選ばれた場合、または接続先がすでにわかっている場合にのみ使用します。

形式使用する状況
{ profileDir }複数のブラウザーが実行中の場合に、特定のブラウザーを対象にします。<profileDir>/DevToolsActivePort を直接読み取ります。
{ wsUrl }ws://…/devtools/browser/<uuid> がすでにわかっている場合(例:別の場所からパイプで渡された場合)。
await session.connect({ profileDir: '/Users/<you>/Library/Application Support/Google/Chrome' })
await session.connect({ wsUrl: 'ws://127.0.0.1:9222/devtools/browser/<uuid>' })

OS ごとのプロファイルパス — { profileDir } と組み合わせて使用します。

  • macOS:~/Library/Application Support/<Browser>(例:Google/Chrome、Comet、BraveSoftware/Brave-Browser、Arc/User Data)
  • Linux:~/.config/<browser>(例:google-chrome、chromium、BraveSoftware/Brave-Browser)
  • Windows:%LOCALAPPDATA%\<Browser>\User Data(例:Google\Chrome、Microsoft\Edge、BraveSoftware\Brave-Browser)

候補ごとの WS 接続タイムアウトのデフォルトは 5s です。実行中のブラウザーは約 100ms 以内に接続の開始・終了に応答するため、5s あれば十分です。5s では短すぎるのは、Chrome に Allow ポップアップが表示され、ユーザーのクリックを待っている場合だけです。その可能性がある場合は、timeoutMs: 30000 を渡します。

await session.connect({ profileDir: '/Users/<you>/Library/Application Support/Google/Chrome', timeoutMs: 30_000 })

No detected browser accepted a connection と表示された場合 — ブラウザーには DevToolsActivePort ファイルがありますが、現在 WS 接続を受け付けているブラウザーがありません。最もよくある原因は、リモートデバッグが有効になっているものの、ユーザーがまだプロンプトの Allow をクリックしていないことです。Allow をクリックしてから再試行するよう伝えてください(または timeoutMs を増やしてください)。

対象(タブ)の選択

connect() の後に session.use(targetId) を一度呼び出すと、それ以降のページレベルの呼び出し(Page/DOM/Runtime/Network など)は、その対象の sessionId に自動的にルーティングされます。Browser.* と Target.* の呼び出しは、常にブラウザーエンドポイントに送られます。

const tabs = await listPageTargets()                     // no args; uses the connected session
const sid  = await session.use(tabs[0].targetId)
await session.Page.enable()
await session.Page.navigate({ url: 'https://example.com' })

listPageTargets() は CDP の Target.getTargets を使用するため(/json ではありません)、Chrome 144+ でも動作します。chrome:// と devtools:// の URL はすでに除外されています。同等の生の呼び出し:

const { targetInfos } = await session.Target.getTargets({})
const tabs = targetInfos.filter(t => t.type === 'page' && !t.url.startsWith('chrome://') && !t.url.startsWith('devtools://'))

タブを切り替えるには、session.use(otherTargetId) を呼び出します。デタッチするには、session.setActiveSession(undefined) を呼び出します。

イベント
// Subscribe (returns an unsubscribe fn)
const off = session.onEvent((method, params, sessionId) => { ... })

// Or wait for a single matching event with optional predicate + timeout
await session.Network.enable()
const ev = await session.waitFor(
  'Page.frameNavigated',
  (p) => p.frame.url.includes('example.com'),
  10_000
)
呼び出し間での状態の保持

各スニペットは独自の非同期ラッパー内で実行されるため、let/const の宣言は戻り時に消失します。データを後続の呼び出しに引き継ぐには、globalThis にアタッチします。

browser-harness-js '(await listPageTargets()).forEach((t,i)=>globalThis["tab"+i]=t.targetId)'
browser-harness-js 'await session.use(globalThis.tab0)'
browser-harness-js 'await session.Page.navigate({url:"https://example.com"})'

session 自体、アクティブな sessionId、イベントサブスクライバーはサーバーによってすでに保持されます。グローバル変数が必要なのは、その場限りのデータだけです。

実行中の Chrome への接続(chrome://inspect の手順)

ユーザーがすでに実行しているブラウザーに接続する場合:

  1. まず引数なしで await session.connect() を試します — 自動検出は DevToolsActivePort を介して、すべての Chromium ベースのブラウザーに対応します。これが成功すれば完了です。
  2. 自動検出で No running browser with remote debugging detected が返された場合、ユーザーがリモートデバッグを有効にする必要があります。inspect ページを開きます。
    # macOS — prefer AppleScript over `open -a` (reuses current profile, avoids the profile picker)
    osascript -e 'open location "chrome://inspect/#remote-debugging"'
    
    # Linux
    google-chrome 'chrome://inspect/#remote-debugging'     # or: chromium, google-chrome-stable
    
    # Windows (PowerShell)
    Start-Process chrome 'chrome://inspect/#remote-debugging'
    
    macOS の AppleScript 経由の方法だけがプロファイル選択画面を回避します。Linux/Windows では先にプロファイルを選択するよう求められる場合があります。
  3. chrome://inspect で 「Discover network targets」 にチェックを入れ、Chrome のプロンプトが表示されたら Allow をクリックします。
  4. 自動検出で誤ったブラウザーが選ばれた場合(複数のブラウザーが実行中で、特定のものを使いたい場合):await detectBrowsers() で一覧を取得してから、await session.connect({ profileDir: <the one you want> }) を実行します。
  5. session.connect() が No detected browser accepted a connection を返した場合、ユーザーはリモートデバッグを有効にしていますが、まだ Allow をクリックしていません。クリックして再試行するよう伝えるか、クリックを待つために timeoutMs: 30000 を渡します。

ターゲット(タブ)の操作

  • Chrome の内部ページを除外します。 listPageTargets() はすでに chrome:// と devtools:// の URL を除外します。Target.getTargets() を直接呼び出す場合は、手動でフィルタリングしてください。
  • CDP のターゲット順と、タブストリップに表示される順序は一致しません。 ユーザーが「見えている最初のタブ」と言った場合は、スクリーンショットまたはページタイトルで特定してください。Target.activateTarget で切り替えられるのは、既知の targetId のみです。

メソッドを調べる

型定義を含む全 API は <skill-dir>/sdk/generated.ts(約 655 KB)にあります(読み込まれるのはこのファイルを読んだ場合のみです)。各メソッドには CDP の説明が JSDoc コメントとして記載され、ドメインごとの名前空間に型定義された *Params/*Return インターフェースがあります。

grep -n "navigate" <skill-dir>/sdk/generated.ts | head

SDK の再生成

上流のプロトコル JSON が変更されたら、sdk/browser_protocol.json および/または sdk/js_protocol.json を置き換えて、次を再実行します。

cd <skill-dir>/sdk && bun gen.ts
browser-harness-js --restart   # pick up the new bindings

ファイル

すべてのパスは <skill-dir>(インストール先。このドキュメントの冒頭を参照)からの相対パスです。

  • /usr/local/bin/browser-harness-js → <skill-dir>/sdk/browser-harness-js(CLI)
  • sdk/repl.ts — HTTP サーバー(127.0.0.1:9876 での Bun.serve)
  • sdk/session.ts — Session クラス(トランスポート、接続、ターゲットのルーティング、イベント)
  • sdk/generated.ts — コード生成の出力:すべての CDP メソッドを型付きラッパーとして定義
  • sdk/gen.ts — コード生成スクリプト
  • sdk/{browser,js}_protocol.json — 上流のプロトコル(ベンダー化済み)

コメント