custom-chrome-dev-mcp
Custom
Custom Chrome Dev MCP
ローカル専用のMCP(Model Context Protocol)サーバーです。MCPクライアント(Claude Codeなど、MCPを話せるあらゆるクライアント)が、人間と同じように実際のChromeブラウザを操作できます。テレメトリなし、Third-partyサービスなし、クラウドなし。すべては共有トークンに守られ、あなたのマシン上だけで完結します。
ナビゲーション、タブ、知覚、操作、trusted入力、可観測性、キャプチャにわたる合計45個のツールを提供します。
由来
このプロジェクトは、Chrome公式のブラウザMCPに触発されています。Chrome DevToolsチームが公開したChrome DevTools MCPサーバーは、AIエージェントがスクレイピングしたHTMLではなく、DevTools Protocolを通じてブラウザを操作すべきだと初めて展開しました。
私たちはそのアイデンティティを複製し破壊しているのであって、出荷しているのではありません。 取り入れたものは次の通りです:
前提 ブラウザを、MCPツールの組み合わせとしてエージェントへ公開する。
アクセシビリティ・ファーストの知覚 大量の素のHTMLを渡さず、安定した要素参照を持つコンパクトなa11yアウトラインをモデルに渡す。
入力レイヤーとしてのChrome DevTools Protocol ページに見破られて無視できる合成イベントではなく、実際のtrustedなイベントを届ける。
このプロジェクトが意図的に異なる点:
Chrome DevTools MCP | Custom Chrome Dev MCP | |
ブラウザ | デフォルトでは専用ユーザーデータディレクトリを持つ独自のChromeを起動。 | あなたが開き終えたChrome・実際に動かすのは、あなかがいます。 |
アタッチ | DevTools Protocolエンドポイント経由でブラウザに接続します。 | ブラウザ内部に住むChrome拡張機能、あなたが選択したタブに向かいます。 |
主な目的 | ページのデバッグ、検査、プロファイリング | そのページを使う人間のように振る舞うこと |
この最後の行がこのリポジトリの要点です。Chrome DevTools MCPは、たまにブラウザを動かすデバッグツールです。一方これは、たまたまデバッグに役立つ、人間を模るためのツールです。
⚠️ GoogleやChromeチームとは、提携・承認・サポートは一切ありません。 これは、彼らの設計から学び、破骸を目的とした、独立した再スキャンです。 公式サポートが欲しい場合は、公式サーバーをお使いください。
Related MCP server: monkeysee
人間らしさを維持する工夫
多くのブラウザ自動化は簡単に見分けがつきます。isTrusted=falseの合成イベント、実際に動かないフォーカス、一瞬で入力されるフィールド、履歴のないきれいな自動化プロファイル。それらはどれもシグナルです。
このプロジェクトは、それらを排除しようとしています:
本当のあなたのプロファイル。 何度も操作を、あなたが既に使ているChrome上で実行します。クッキーも、ログインも、拡張機能も、履歴も、すべて維持されたまま。どこからも「まっさらな自動化」と区別を持って指摘されるものはありません。
Trusted入力。
realClick、realType、press、hover、dragはDevTools Protocol経由でイベントを発行するため、ページには物理的なマウス・キーボードが生成するのと同等のisTrusted=trueイプロセントが届きます。本物のフォーカス。 フィールドのフォーカスを合わせるクリックでは、画面の裏で
.valueを代入するのではなく、実際にフォーカスを正しい順序で移します。実際のキーストローク。
pressは合成inputイベントを1つ送るのではなく、正しいテンコードとモディファイルを持つrawKeyDown/char/keyUpシーケンスを送出します。読み戻し検証。
fillはフィールドに実際にそのテキストが入ったことを確認します。ページが入力を受け取らなかったとき、エージェントは、人間と同じようにそれに気づけます。
目標は、ページが、あなたがキーボードの前に座って操作している人と同じように、エージェントに対しても動作することです。
高速な合成ツール(click、type)も残っています。これらはより速く、多くのWebサイトで利用可能です。ページがそれらを無視する場合は、trusted系のツールに頼ってください。
動作の仕組み
トランスポートは1つです。MCPクライアントはstdioでサーバーに接続し、サーバーは、構成の長命なhubプロセスが保持するローカルWebSocketを介してChrome拡張機能に中継します。
MCP client 1 (Claude) <-stdio-> bin/custom-chrome-dev-mcp.js ─┐
MCP client 2 (Claude) <-stdio-> bin/custom-chrome-dev-mcp.js ─┼─ src/hub.js (127.0.0.1:9876)
MCP client N (Claude) <-stdio-> bin/custom-chrome-dev-mcp.js ─┘ │
│ WebSocket
▼
Chrome extension -> active tabなぜ独立したハブプロセスなのか。 ポート9876を専有できるプロセスは1つだけですが、Claude Codeのセッションが複数開いている場面で、すべてがブラウザを参照したいケースが考えられます。そこで、ソケットを個々のセッション内部ではなくsrc/hub.jsに置いています。各クライアントはrole:"mcp"としてハブに接続し、拡張機能はrole:"extension"としてハブに接続し、ハブが仲介します。最初のセッションが起動したとき、ハブはデタッチされデブプロセスとして生成されるため、セッションが終わってもハブは存続します。それ以降のセッションは、すでに使っているハブを見つけます。
拡張機能の中には3つのレイヤーがあります:
Walker(
page/walker.js) — ページのISOLATEDワールドに注入されます。要素解決、安定したeN参照、高速な合成DOM操作を担当します。CDP(
cdp/) — trust時に入力、ページコンテキストでのevaluate、全ページのスクリーンショット、コンソールのlogやネットーネットのバッファは、この領域にで処理します。chrome.debuggerを使います。Recording(
recording/) — CDPの画面描画フレームを、オフスクリーンドキュメントのMediaRecorderが.webmにエンコードします。
🔒 拡張機能は、共有トークン(
src/config.jsとextension/src/config.jsで同じ値になるAUTH_TOKEN)でハブに認証します。ハブは、異なる値を見せたピアを遮断します。
前提条件
要件 | 確認コマンド | |
Node.js | 18 以降(22 で開発) |
|
Chrome | Google Chrome / Chromiumの、最新に近いバージョン |
|
MCPクライアント | Claude Code、またはstdioでMCPを実装しているクライアント |
|
グローバルインストールも、ビルドステップも、サインアップするようなサービスもありません。ランタイムのデペンデンシは @modelcontextprotocol/sdk と ws の2つだけです。しかもすべてが127 127.0.0.1上で動き続けます。
ローカルでのセットアップ
4つのステップと、最後の確認までで、所要時間は5分程度です。
1. クローンしてインストール
git clone <your-fork-url> custom-chrome-dev-mcp
cd custom-chrome-dev-mcp
npm installブラウザを接続する前に、ツリーが正常に揃っていることを確認します。オフラインのテストはブラウザを必要とせず、1秒未満で終わるので安心です:
npm test22 passed と表示されたらOKです。失敗した場合は、次に進む前に修正してください。次の全工程がうまく動かなくなります。
2. 拡張機能をChromeへ読み込む
chrome://extensionsを開く。Developer mode(右上のトグル)をオンにする。
Load unpacked をクリックし、
extension/フォルダ(の中のmanifest.jsonではなく、フォルダ自体)を選択する。リストに Custom-chrome-dev-mcp が表示されます。
⚠️ 実際にブラウジングに使っているプロファイルで読み込んでください。 Chrome はプロファイルごとに拡張を管理するため、「Profile Observation」に読み込んだ拡張は、通常の「Default(デフォルト)」のウィンドウから見えません。後でツールがタブを認識しない場合、あるいはハブが
textの形容(extension connected)を取らない場合、最初に確認すべき箇所です。chrome://versionに表示される、現在のプロファイルパス(Profile Path)をご覧ください。
拡張機能IDは、 extension/manifest.json の public key に固定されています。そのため、どのマシンでも同じIDになります。環境間でコピーするものはありません。
3. MCPサーバーをクライアントに登録する
CLIを使う 場合は、リポジトリをクローンした絶対パス(プロジェクトルートで pwd を打つと表示されます)に置き換えます:
claude mcp add -s user custom-chrome-dev-mcp -- node /ABSOLUTE/PATH/TO/custom-chrome-dev-mcp/bin/custom-chrome-dev-mcp.js-s userはプロジェクト全プロジェクトに登録します。-s localはこのプロジェクトだけに適用します。登録するのは
bin/custom-chrome-dev-mcp.jsです。このファイルがあったポイントなので、src/server.jsを指しても機能しません。パスは 絶対パス でなければなりません。相対パスだと、クライアントの起動時のディレクトリ解釈されます。
次のコマンドで確認できます:
claude mcp list実行の結果、✔ Connected よとなりが示されれば、確定です。
⚠️
~/.claude.jsonを手作業で編集しないでください。 このファイルは大きいため、コンマを1つ間違えるだけでClaude Code全体が壊れます。上記のCLIコマンドは安全に編集します。
mcpServers の下にサーバー項目を追加します:
{
"mcpServers": {
"custom-chrome-dev-mcp": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/custom-chrome-dev-mcp/bin/custom-chrome-dev-mcp.js"]
}
}
}4. MCPクライアントを再起動する
MCPクライアントは起動時、ツール一覧を一度だけ読み取ります。セッションの途中でサーバーを追加しても、再起動まで反映されません。Claude を再起動すると、45個のツールが表示されます。
再起動時に、クライアントはサーバーをT起動し、サーバーは 127.0.0.1:9876 で何も待機していなければ src/hub.js を生成します。
5. チェーン全体を検証する
スタックは client → server → hub → extension → tab の形です。どのリンクが切れているのかを推測するのではなく、全体を確かめることが重要です。
# The hub is up, and the extension found it:
tail -f "$TMPDIR/custom-chrome-dev-mcp-hub.log"
# [hub] listening on 127.0.0.1:9876
# [hub] extension connected <- this line is the handshake succeeding
# Who owns the port (should be src/hub.js from THIS repo):
lsof -nP -iTCP:9876 -sTCP:LISTEN続いて、クライアントに listTabs を依頼してください。開いているタブのJSON配列が返ってきたら、すべてのリンクが機能しています。次に screenshot を実行すると、PNG が ~/Downloads に保存され、かつインラインでも返ってきます。
拡張機能自身のコンソールを見るには:chrome://extensions → Custom-chrome-dev-mcp → service worker → Inspect で確認します。拡張側の障害はここに表示され、MCPクライアントには表示されません。
6. 実際に使う前に共有トークンに変えましょう
AUTH_TOKEN には、**src/config.js と extension/src/config.js に同じデフォルト値が入っています。このトークンが、自分のマシン上の別プロセスがあなたのログイン済みブラウザを操作することを防ぐ唯一の壁です。独自の値に変え、両方のファイルで変更してから、拡張機能を再読み込みしてください(オフラインテストが両者の一致を検証します)。
コード変更後の反映方法
2つの部分のリロード方法は異なるため、これを間違えると他の何よりも時間を割くことになります:
変更した対象 | 反映するには |
| 拡張機能ページ( |
| MCP クライアントを再起動します。サーバープロセスは長期間存在し、古いツールスキーマを保持しています。 |
|
|
トラブルシューティング
症状 | 原因 | 修正方法 |
| パスが正しくないか、 |
|
クライアントにツールがまったく表示されない | セッションの途中で登録された | MCP クライアントを再起動する |
Hub ログに | 拡張機能が読み込まれていない、別の Chrome プロファイルで読み込まれている、または2つの |
|
ツール呼び出しがハングして、最終的にタイムアウトする | サービスワーカーが停止した、または拡張機能側で例外が発生した | サービスワーカーのコンソールを開き、reload ↻ をクリックする |
ポート | このプロジェクトの別クローンから起動している hub がポートを占有している |
|
| Chrome が古いビルドを実行したままである | reload ↻ をクリックする |
|
| リストを編集する。最初からプレースホルダのエントリが入っている |
|
| ガードを削除するか、実際の URL を指すようにする |
スクリーンショットのパスが拒否される | 書き込みがキャプチャディレクトリ内に制限されている | そのディレクトリ内のファイル名またはパスを使う |
ツールが誤ったタブを操作する | バックグラウンドのタブがフォーカスを奪った |
|
設定
どちらも起動時に src/config.js が読み取るオプションの環境変数です。
変数 | デフォルト | 説明 |
|
| スクリーンショットと録画を書き込める唯一のディレクトリです。 |
|
| Hub 用のポート。 |
実際に使うときに合わせて変更したい値がもう1つあります。AUTH_TOKEN です。これは
src/config.js と extension/src/config.js に同じ値で定義します。自分の値を指定してください。
他のローカルプロセスがあなたのブラウザを操作するのを防ぐのがこの値です。
利用可能なツール(45)
要素は次の3つの方法で対象にします。selector(CSS)、ref(snapshotA11y が返す安定した eN の ID)、
または name(アクセシブルネーム。例:ボタンのラベル)です。以下の「target」はこれら3つのいずれかを指します。
すべてのツールで使える共通パラメータ
tabId— 現在アクティブなタブではなく、特定のタブに対して操作する。frameId(listFramesから取得)— 特定のフレーム内で操作する。トップのドキュメントからはスクリプトを実行できないクロスオリジンの iframe も対象になる。expectUrl— ガード:タブの URL がこの部分文字列を含む場合にのみ操作を許可する。
セッション全体で使うタブを useTab で固定しておくと、バックグラウンドのタブ(自動再生の動画や通知ポップアップ)が
フォーカスを奪って操作対象を誤らせるのを防げます。
ナビゲーション
ツール | 引数 | 説明 |
|
| タブを指定 URL に移動させます(ページは置き換わります)。 |
|
| 現在のページを残したまま、新しい先頭タブで URL を開きます。 |
| - | 履歴を戻る / 進む。 |
|
| リロードします。任意でキャッシュをバイパスします。 |
| - | タブの URL / タイトル(内部ページでも機能します)。 |
|
| タブの読み込みが完了するまでブロックします。 |
タブとフレーム
ツール | 引数 | 説明 |
| - | すべてのウィンドウにあるすべてのタブ( |
|
| タグとそのウィンドウにフォーカスを当てる。 |
|
| 指定した ID のタブを閉じる。 |
|
| 作業タブを固定して、以降のどのツールも OS のフォーカス状態に関係なくそのタブを対象にする。 |
| - | 固定を解除する。ツールはアクティブなタブを対象にする通常動作に戻る。 |
| - | クロスオリジンも含むすべてのフレームを |
知覚
ツール | 引数 | 説明 |
| - | 表示されている操作可能な要素の簡潔なアクセシビリティ一覧を |
| - |
|
|
| 要素1つの |
|
| 属性を返す。存在しない場合、ライブ DOM のプロパティ( |
|
| 一致するすべての要素の text / href / value / visible を一度に返します。 |
| - |
|
操作(合成イベント・高速)
ウォーカーが送出する非信頼イベントです。高速で、ほとんどのサイトには十分です。
ツール | 引数 | 説明 |
| target | バブリングする |
| target, | ネイティブセッターでフィールドの値を設定( |
| target, | フォーカス+セット+読み戻し確認。テキストが反映されていなければスロー。最も確実なテキスト入力手段なので、クリック→タイピングよりこちらを優先する。 |
| target, | スクリーンショット無しでテキスト(部分一致)と値の一致を検証する → |
| target?, | 要素が表示されるまでスクロールするか、ウィンドウをスクロールします( |
| target, | value または表示ラベルで |
| target, | チェックボックス / ラジオボタンを指定した状態に設定。すでに同じ状態であればクリックしません。 |
| target, | 所属フォームを |
| target または | 要素が見つかるか、指定したテキスト部分文字列が現れるまで待機します。 |
信頼される入力とエミュレーション — CDP
isTrusted=true の実イベントを送ります。これらは chrome.debugger を接続するため、タブに黄色の 「デバッグ中」 バナーが
常に表示されます。
ツール | 引数 | 説明 |
| target / | 信頼済みクリック。右クリックやダブルクリックも含みます。 |
| target?, | 信頼済みテキスト挿入。指定があれば最初にそのターゲットにフォーカスします。 |
|
| 信頼済みキーとコンビネーション: |
| target / | 実際のマウスを要素上に移動して |
|
| 信頼済みのプレス→ムーブ→リリースによるドラッグ&ドロップ。 |
|
| OSのファイル選択ダイアログを介さずに |
|
| レスポンシブチェックのためのビューポート/デバイスをエミュレートします。 |
|
| 次に来る |
| - | デバッガーを切り離してバナーを消します。次の CDP 呼び出しの際に再接続されます。 |
可観測性 — CDP、タブごとにバッファリング
キャプチャはデバッガが接続したときに開始されるため、ページ読み込み時の動作を取得したい場合は、最初の CDP 呼び出しの後にページを再読み込みしてください。
ツール | 引数 | 説明 |
|
| バッファされたコンソールログ、警告、エラー、未捕捉された例外。 |
|
| バッファされたリクエスト:メソッド、URL、ステータス、タイプ、タイミング。 |
|
| 1件のリクエストを完全な形で取得します。 |
|
| CDP 経由でページの実際のコンテキストで JS を実行します。 |
キャプチャ
キャプチャディレクトリ(デフォルトは ~/Downloads — 設定 を参照)に保存されます。
ツール | 引数 | 説明 |
|
| 表示中のビューポートを PNG/JPEG で保存 — ディスクに保存され、 |
|
| ビューポートの外まで含む、スクロール可能なページ全体を CDP 経由で取得します。 |
|
| タブの録画を |
path はファイル名、またはキャプチャディレクトリの内側へのパスです。存在しないサブフォルダは作成されます。ディレクトリ外へ解決されるものは拒否されます。
最初の実動実行
セットアップ手順5が結線を検証します。ここではそれに続く興味深い部分、つまりページがスクリプトではなく実際のユーザーとして認識すること、が実証されます。クライアントを任意のページに向けて、以下の内容を依頼してください:
snapshotA11y— コンパクトなアウトライン。ターゲット指定用のeNリファレンスが付いています。realClick {ref:"e3"}— 信頼されたクリック。タブに黄色の 「デバッグ中です」 バナーが表示されます。これは CDP のアタッチによるもので、あえて見えるようにしてあります。evaluate {expression:"'ok'"}— content script の CSP を迂回したページコンテキストの JS 実行。screenshot— キャプチャディレクトリに保存された PNG が、さらにインラインでも返されます。record {action:"start"}…record {action:"stop", path:"clip.webm"}— タブの.webmを生成します。ツールバーのクリックもユーザー操作も不要です。ツールバーのアイコンは意図的に何も起動しません。detach— バナーを消去します。
信頼された操作による違いを実感するために、リスナーを仕掛けて比較してみてください:
// via evaluate
window.__e = []; document.querySelector("button")
.addEventListener("click", e => window.__e.push(e.isTrusted));click は false を報告します。一方 realClick は true を報告します。この対比こそがこのプロジェクトの存在理由であり、ブラウザテストレーンはその点を直接アサートします。
テストの実行
テストスイートには2つのレーンがあり、その分割こそがポイントです。
オフラインレーン — ブラウザ不要、CI で実行
npm test # node test/run.mjs --lane=offline1 秒未満で完了し、必要なのは Node だけです。SDK のインメモリトランスポートを介して src/server.js に対して実際の MCP ハンドシェイクをプロセス内で 実行するため、サーバーが実際に公開している表面に対して検証を行います:
公開されているすべてのツールに拡張ハンドラが存在し、その逆も同様であること — ミラー化されたアーキテクチャが招きやすい失敗です。
同じツール名が2つのハンドラグループによって要求されないこと(スプレッドでマージされるため、重複は暗黙的に失われます)。
すべてのツールが実際の説明文と、共通の
tabId/frameId/expectUrlスコープを持つこと。すべてのツールが最低1件のテストで実行されること — テストなしでツールを増やすと、ブラウザなしでも CI が失敗します。
キャプチャパスの許可リストが
..、深い..、絶対パス、シンボリックリンクによる逃げ道を現実のリゾルバに対して実際に拒否していること。禁止リストが挙動によって確認されていること — 主張する対象をブロックし、一般のサイトを過剰にブロックしないこと。
ハブがループバックのみにバインドし、両側でトークンが一致し、マニフェストが過度に広い権限を要求せず、ツールバーのアイコンが意図的に何もしない状態であり、
*.pemがコミットされていないこと。
ブラウザレーン — 実際の Chrome を操作
# 1. Disconnect the MCP client (close Claude Code, or disable this server for the run)
# 2. Free port 9876 - the hub is long-lived and outlives the session that spawned it
pkill -f src/hub.js
# 3. Start the suite; it binds 9876 itself and waits for the extension
npm run test:browser
# 4. Reload the extension in chrome://extensions so it connects to the suite⚠️ ステップ1は必須です。 接続中の MCP クライアントは、ソケットが消えたことを検出すると、ハブを約 ~1.2 秒ごとに再生成します。そのため、ポート 9876 を再び占有し、スイートは
EADDRINUSEで終了します。クライアントがアタッチされたままハブを終了しても解決にはなりません — クライアントは別のハブを起動するだけです。
このスイートは、フィクスチャサーバーと、実際のハブと同じワイヤプロトコルを話すブリッジを立ち上げるため、実際のメッセージ契約を実行します。各スイートはツールグループのミラーになっており、すべてのテストはリセットされたページを基礎としたフィクスチャから開始されるため、どのテストも別のテストの変更を引き継ぎません。
最後にツールカバレッジが表示され、45 個のツールのうち実行されないものがあれば失敗します。
オプション
コマンド | 効果 |
| オフラインレーンのみ(CI のゲート) |
| ブラウザレーンのみ |
| 両方 |
| 実行せずにすべてのスイートとテストを一覧表示する |
| スイート/名前が一致するテストだけを実行する |
テスト構成
test/
├── run.mjs # CLI: lanes, filtering, coverage, reporting
├── lib/
│ ├── runner.js # suite registry, isolation, timeouts
│ ├── assert.js # assertions with diagnostic messages
│ ├── wait.js # eventually() - polling, not fixed sleeps
│ ├── mcp-probe.js # real in-process MCP handshake
│ ├── bridge.js # stands in for the hub; tracks tool coverage
│ ├── fixture-server.js # serves the fixture pages
│ └── page.js # the browser session + per-test reset
├── fixtures/
│ ├── index.html # the fixture page (a real file, with __reset())
│ └── frame.html # child frame, for frameId targeting
└── suites/
├── 01-contract.suite.js # offline
├── 02-security.suite.js # offline
├── 10-navigation.suite.js
├── 20-tabs.suite.js
├── 30-perception.suite.js
├── 40-interaction.suite.js
├── 50-trusted-input.suite.js
├── 60-observability.suite.js
└── 70-capture.suite.jsセキュリティに関する注意
この拡張は、ログイン済みのブラウザを操作できます。必ず読みかつてください。
ループバックのみ。 ハブは
127.0.0.1にバインドするため、LAN からは到達できません — このマシン上のプロセスだけがアクセスできます。トークンハンドシェイク。 ピアェアは接続時に
AUTH_TOKENを提示する必要があり、提示しない場合はハブが切断します。出荷時のデフォルトから変更してください(src/config.jsとextension/src/config.js内の同一定数)— これが、他のローカルプロセスによるブラウザ操作を防ぐものです。ファイルの書き込みはキャプチャディレクトリに限定されます。
src/capture/capture-path.jsは要求されたすべてのパスを解決し、..の走査およびシンボリックリンクされたサブディレクトリ経由のものも含め、外部に解決されるものを拒否します。これは見た目以上、任意のパスへの書き込みは事実上のコード実行になります。ホスト禁止リスト。
extension/src/config.jsのBANLISTは、重要なドメイン(銀行、PayPal、Gmail)へのナビゲーションとスクリプト実行をブロックします。必要に応じて調整してください。注意: スクリーンショットと録画はレンダリングされたピクセルを取得するものであり、禁止リストではフィルタされません。デバッガのバナーは仕様です。 CDP ツールは
chrome.debuggerにアタッチし、永続した黄色の 「デバッグ中」 バーを表示します。これは、何かがタブを操作しているという視覚的な信号です。detachで除去できます。evaluateは、ページの実際のコンテキストで任意の JS を実行します。内部ページは対象外です — 拡張は
chrome://およびchrome-extension://の URL をスクリプト化できません。署名するキーはこのリポジトリに置かれていません。 拡張 ID は
extension/manifest.json内の公開keyによって固定されます。一致する秘密鍵はバージョン管理の外に置く必要があります(.gitignoreが*.pemをブロック)。コードと同じ ID で.crxを再パッケージするときにのみ必要で、アドオンとして読み込む場合は使用しません。
アーキテクチャ
サーバーと拡張はミラー構造です。src/tools/ の各ツールグループは、extension/src/handlers/ に同じ名前のハンドラファイルがあります。ツールを追加するには、そのペア双方に手を加えます — 片側はスキーマとドキュメント、もう一方は実装です。
グループ | サーバー(スキーマ + ドキュメント) | 拡張(実装) |
navigation |
|
|
tabs |
|
|
perception |
|
|
interaction |
|
|
trusted input |
|
|
observability |
|
|
capture |
|
|
その他のすべてはサポートインフラです:
bin/custom-chrome-dev-mcp.js- MCP クライアントに登録する実行可能ファイルです。サーバーを起動する以外のことはしません。src/config.js/extension/src/config.js- 調整可能な全設定をサイドごとに1ファイルで管理します。AUTH_TOKENとポートは2つの間で一致させる必要があります。src/relay/hub-client.js-role:"mcp"として hub に接続し、存在しない場合は hub を起動し、各ツール呼び出しをソケット上のリクエスト/レスポンスに変換します。src/hub.js-ws://127.0.0.1:9876を所有する長期的なリレー。拡張機能のソケットを1つと各セッションのクライアントを保持し、それらの間で多重化します。回線上で ID を付け直し(セッション間で衝突する可能性がある)、すでにポートを所有する hub がある場合は自身を終了します。src/capture/capture-path.js- 書き込み許可リスト。すべてのキャプチャパスはここを経由します。extension/src/connection.js- hub ソケットとハートビートを担当します。MV3 のサービスワーカーは、約30秒間アイドル状態が続くと破棄され、それによってソケットは静かに切断されます。30秒未満のハートビートが両方を生かしたままにし、アラームが強制終了後にワーカーを復活させます。extension/src/tabs.js- 呼び出しがどのタブを対象にするか(明示的なtabId> 固定タブ > アクティブタブ)、expectUrlガード、禁止リストのチェックを行います。extension/src/walker-bridge.js+extension/src/page/walker.js- 安定した element-ref システムを備えた注入済み ISOLATED-world スクリプトと、それに到達できる唯一のモジュール。extension/src/cdp/-session.js(アタッチ/デタッチ、cdp()、要素の中心)、keyboard.js(キー名 → CDP キーイベント)、dialogs.js(ネイティブダイアログのポリシー)、buffers.js(コンソール + ネットワークリングバッファ、タブごとに最大500件)。extension/src/recording/-chrome.tabCaptureには MCP 呼び出しにないユーザージェスチャーが必要です。そのため、録画は代わりに CDP screencast を使用します。JPEG フレームをオフスクリーンのMediaRecorderに中継します(サービスワーカーには DOM がないため)。test/- 2レーン構成のスイート。ブラウザを必要としないオフライン CI ゲートと、実際の Chrome を操作するブラウザレーンがあります。テストの実行 を参照してください。
プロジェクト構成
.
├── bin/
│ └── custom-chrome-dev-mcp.js # executable entry - register THIS with your client
├── src/
│ ├── server.js # composes config + relay + tool registry
│ ├── config.js # port, token, capture dir, timeouts
│ ├── hub.js # long-lived relay owning :9876
│ ├── relay/
│ │ └── hub-client.js # session -> hub socket; call()
│ ├── capture/
│ │ └── capture-path.js # write allowlist for screenshots/recordings
│ └── tools/ # ONE FILE PER TOOL GROUP - the public surface
│ ├── index.js # the registry
│ ├── schemas.js # shared arg shapes + passthrough helper
│ ├── navigation.js
│ ├── tabs.js
│ ├── perception.js
│ ├── interaction.js
│ ├── trusted-input.js
│ ├── observability.js
│ └── capture.js
├── extension/ # Chrome MV3 extension
│ ├── manifest.json
│ └── src/
│ ├── background.js # service worker entry - wiring only
│ ├── config.js # token, banlist, buffer caps, asset paths
│ ├── connection.js # hub socket + MV3 keepalive heartbeat
│ ├── tabs.js # tab resolution, pinning, ban check
│ ├── walker-bridge.js # channel to the injected page script
│ ├── cdp/
│ │ ├── session.js # attach/detach, cdp(), element centres
│ │ ├── keyboard.js # key names -> CDP key events
│ │ ├── dialogs.js # native alert/confirm/prompt policy
│ │ └── buffers.js # console + network ring buffers
│ ├── recording/
│ │ ├── recorder.js # CDP screencast -> offscreen encoder
│ │ ├── offscreen.html
│ │ └── offscreen.js # MediaRecorder host
│ ├── page/
│ │ └── walker.js # injected DOM driver (ISOLATED world)
│ └── handlers/ # MIRRORS src/tools/ - one file per group
│ ├── index.js # the handler table + dispatch
│ ├── navigation.js
│ ├── tabs.js
│ ├── perception.js
│ ├── interaction.js
│ ├── trusted-input.js
│ ├── observability.js
│ └── capture.js
└── test/ # two lanes: offline (CI) + browser
├── run.mjs # CLI entry
├── lib/ # runner, assertions, bridge, fixtures, session
├── fixtures/ # the fixture pages, as real files
└── suites/ # one suite per tool groupクレジット
Chrome DevTools MCP(Chrome DevTools チーム制作)に触発されています。独立した再実装であり、Google とは関係なく、Google からの承認やサポートを受けていません。
ライセンス
MIT. Copyright (c) 2026 Haba Andrei.
自由に使って、フォークして、リリースしてください。唯一の条件は、著作権表示と許諾表示が実質的なコピーにそのまま含まれることです。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables MCP clients to control and interact with the user's real Chrome browser session, leveraging existing logins, cookies, and extensions for AI-driven automation.5MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to drive a real, logged-in Chrome browser for web automation tasks like navigation, clicking, typing, and screenshotting.11MIT
- FlicenseNot gradedqualityCmaintenanceDrive your real, signed-in Chrome browser from any MCP client, enabling browser automation such as navigation, clicking, typing, and screenshots through standard MCP tools.1
- AlicenseCqualityAmaintenanceMCP server for browser automation that drives Chrome via an extension, preserving login state and offering 45 tools for navigation, interaction, scraping, and screenshots.534MIT
Related MCP Connectors
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/HabaAndrei/custom-chrome-dev-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server