chrome-devtools-mcp について
chrome-devtools-mcp は、Chrome DevTools を通じて Chrome を操作・検査する MCP サーバーで、ブラウザー自動化やテスト向けです。ページのスナップショット、操作、スクリプト実行、スクリーンショット、性能・アクセシビリティ検査を提供し、拡張機能やメモリ用ツールも任意で有効にできます。
主な機能
- 01ページの移動と読み込み待機
- 02ページ構造の確認と要素操作
- 03スクリプト実行による状態確認
- 04ビューポートのスクリーンショット撮影
- 05性能・レイアウト・アクセシビリティの検査
- 06拡張機能とメモリ用ツールの任意有効化
活用シーン
- 01ブラウザー操作とデータ取得の自動化
- 02ページエラーやネットワーク失敗の確認
- 03異なるビューポートでのレスポンシブ検証
- 04ウェブページ上での拡張機能動作の確認
MCP 対応
MCP サーバーとして、Chrome の操作・検査ツールを MCP クライアントに提供します。ページ ID で対象ページを指定でき、設定フラグで拡張機能やメモリ用ツールを有効にできます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gsmlg-dev/ code-agent --skill chrome-devtools-mcpインストール後、Claude Code で/chrome-devtools-mcpを入力して読み込まれたか確認します。
詳細
コアコンセプト
ブラウザーのライフサイクル:ブラウザーは、永続的な Chrome プロファイルを使用して、最初のツール呼び出し時に自動的に起動します。MCP サーバーの設定で CLI 引数を指定して構成します:npx chrome-devtools-mcp@latest --help。
以下のフラグを指定すると、追加のツールを有効にできます。
- 拡張機能ツールを有効にするには、
--categoryExtensionsフラグを使用します。 - メモリツールを有効にするには、
--memoryDebuggingフラグを使用します。
ページの指定:ページ単位のツールでは、対象のページを指定するために pageId パラメーターが必要です。list_pages を使用して、利用可能なページとその ID(例:pageId: 1)を確認するか、new_page でページを作成したときに返される ID を使用します。
注:evaluate_script でページを対象にする場合は、pageId が必要です。ただし、--categoryExtensions が有効な場合は pageId は省略可能です。その代わりに serviceWorkerId を渡すと、拡張機能のバックグラウンドサービスワーカー内で評価できます。
要素の操作:take_snapshot を使用して、要素の uid を含むページ構造を取得します。各要素には、操作に使用する一意の uid があります。要素が見つからない場合は、新しいスナップショットを取得してください。要素が削除されたか、ページが変更された可能性があります。
ワークフローパターン
ページを操作する前に
- 移動:
navigate_pageまたはnew_page - 待機:探しているものが分かっている場合は、コンテンツが読み込まれるのを確認するために
wait_forを使用します。 - スナップショット:
pageIdを指定してtake_snapshotを実行し、ページ構造を把握します。 - 操作:スナップショットに含まれる要素の
uidをclick、fillなどに使用し、対応するpageIdを渡します。
効率的なデータ取得
- 大きな出力(スクリーンショット、スナップショット、トレース)には
filePathパラメーターを使用します。 - ページネーション(
pageIdx、pageSize)とフィルタリング(types)を使用して、データ量を最小限に抑えます。 - ページの状態を更新する必要がない場合は、入力操作で
includeSnapshot: falseを設定します。
ツールの選択
- 自動化/操作:
take_snapshot(テキストベースで高速なため、自動化に適しています) - 視覚的な確認:
take_screenshot(ユーザーが視覚的な状態を確認する必要がある場合) - 追加の詳細情報:アクセシビリティツリーにないデータには
evaluate_script
並列実行
複数のツール呼び出しを並列で送信できますが、正しい順序を維持してください:移動 → 待機 → スナップショット → 操作。
拡張機能のテスト
拡張機能ツール(install_extension、list_extensions など)は、MCP サーバーの起動時に --categoryExtensions フラグを指定した場合にのみ利用できます。これらのツールが利用できない場合は、MCP サーバーの設定を更新してMCP サーバー(または AI クライアント)を再起動するよう、ユーザーに依頼してください。
- インストール:展開済みの拡張機能へのパスを指定して
install_extensionを使用します。 - 特定:応答から、または
list_extensionsを呼び出して拡張機能 ID を取得します。 - アクションを実行:該当する場合は、
trigger_extension_actionを使用してポップアップまたはサイドパネルを開きます。 - サービスワーカーを確認:
evaluate_scriptでserviceWorkerIdを使用し(pageIdとargsは省略)、拡張機能の状態を確認するか、バックグラウンドアクションを実行します。ページ内で評価する場合は、pageIdを渡し(serviceWorkerIdは省略)ます。 - ページの動作を確認:拡張機能が動作するページに移動し、
take_snapshotを使用して、コンテンツスクリプトが要素を挿入したか、ページを正しく変更したかを確認します。
トラブルシューティング
chrome-devtools-mcp で不十分な場合は、Chrome DevTools UI を使用するようユーザーに案内してください。
chrome-devtools-mcp または Chrome の起動時にエラーが発生した場合は、https://github.com/ChromeDevTools/chrome-devtools-mcp/blob/main/docs/troubleshooting.md を参照してください。
Chrome DevTools MCP の使用方法
重要な制約:スクリーンショットのサイズ制限
API への送信には、いずれかの寸法が 8000px を超えてはならないという厳しい制限があります。ページ全体のスクリーンショットは、この制限を頻繁に超えます。
解決策:デフォルトではビューポートのみのスクリーンショットを常に使用する
// ✓ CORRECT: Viewport-only (default)
take_screenshot({ fullPage: false })
// ✓ CORRECT: Save to filesystem for large pages
take_screenshot({ fullPage: false, path: './screenshots/page.png' })
// ✗ AVOID: Full-page without size check
take_screenshot({ fullPage: true })
ページ全体のスクリーンショットが必要な場合
まずページの高さを確認します。
const height = execute_script('return document.documentElement.scrollHeight')
if (height > 8000) {
take_screenshot({ fullPage: false, path: './screenshot.png' })
} else {
take_screenshot({ fullPage: true })
}
別の方法:スクロールしながらビューポートのスクリーンショットを複数枚撮影します。
take_screenshot({ fullPage: false, path: './top.png' })
execute_script('window.scrollBy(0, window.innerHeight)')
take_screenshot({ fullPage: false, path: './middle.png' })
ナビゲーションとタイミング
ナビゲーション後は、JavaScript の実行とレンダリングを待つため、必ず待機してください。
navigate('https://example.com')
wait(1000) // Minimum recommended wait
// For dynamic apps, wait for specific elements
navigate('https://example.com')
execute_script(`
return new Promise(resolve => {
const check = () => {
if (document.querySelector('#app')) resolve();
else setTimeout(check, 100);
};
check();
});
`)
エラー検出パターン
コンソールエラー
const errors = execute_script(`
return performance.getEntriesByType('navigation')[0].type === 'reload'
? []
: (window.__consoleErrors || []);
`)
ネットワーク障害
const failed = execute_script(`
return performance.getEntriesByType('resource')
.filter(r => r.transferSize === 0 && r.duration > 0)
.map(r => ({ url: r.name, duration: r.duration }));
`)
レイアウトの問題
const issues = execute_script(`
const issues = [];
// Horizontal overflow
if (document.documentElement.scrollWidth > window.innerWidth) {
issues.push({ type: 'horizontal-overflow', width: document.documentElement.scrollWidth });
}
// Elements outside viewport
document.querySelectorAll('*').forEach(el => {
const rect = el.getBoundingClientRect();
if (rect.right > window.innerWidth) {
issues.push({ type: 'overflow-right', element: el.tagName });
}
});
return issues;
`)
レスポンシブテスト
複数のビューポートを効率よくテストします。
const viewports = [
{ width: 375, height: 667, name: 'mobile' },
{ width: 768, height: 1024, name: 'tablet' },
{ width: 1440, height: 900, name: 'desktop' }
];
for (const vp of viewports) {
set_viewport(vp.width, vp.height);
wait(500); // Allow reflow
take_screenshot({
fullPage: false,
path: `./screenshots/${vp.name}.png`
});
}
コンポーネントの状態テスト
ユーザー操作なしでインタラクティブな状態をテストします。
// Hover state
execute_script(`
const el = document.querySelector('#button');
el.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
`);
take_screenshot({ fullPage: false, path: './hover.png' });
// Focus state
execute_script(`
document.querySelector('#input').focus();
`);
take_screenshot({ fullPage: false, path: './focus.png' });
// Active/pressed state
execute_script(`
const el = document.querySelector('#button');
el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
`);
take_screenshot({ fullPage: false, path: './active.png' });
パフォーマンス指標
ウェブバイタルとパフォーマンスデータを収集します。
const metrics = execute_script(`
return {
fcp: performance.getEntriesByName('first-contentful-paint')[0]?.startTime,
lcp: performance.getEntriesByType('largest-contentful-paint')[0]?.startTime,
cls: performance.getEntriesByType('layout-shift')
.reduce((sum, entry) => sum + (entry.hadRecentInput ? 0 : entry.value), 0),
resources: performance.getEntriesByType('resource').length,
totalSize: performance.getEntriesByType('resource')
.reduce((sum, r) => sum + r.transferSize, 0)
};
`);
アクセシビリティチェック
基本的なアクセシビリティ検証を行います。
const a11y = execute_script(`
const issues = [];
// Missing alt text
document.querySelectorAll('img:not([alt])').forEach(img => {
issues.push({ type: 'missing-alt', src: img.src });
});
// Missing form labels
document.querySelectorAll('input:not([aria-label]):not([id])').forEach(input => {
if (!input.closest('label')) {
issues.push({ type: 'missing-label', name: input.name });
}
});
// Empty links
document.querySelectorAll('a').forEach(link => {
if (!link.textContent.trim() && !link.getAttribute('aria-label')) {
issues.push({ type: 'empty-link', href: link.href });
}
});
return issues;
`);
標準的な監査ワークフロー
体系的なページ監査には、次のパターンを使用します。
function audit_page(url, name) {
// Navigate
navigate(url);
wait(1000);
// Screenshot (viewport only to avoid size errors)
const screenshot_path = `./screenshots/${name}.png`;
take_screenshot({ fullPage: false, path: screenshot_path });
// Page metrics
const height = execute_script('return document.documentElement.scrollHeight');
const viewport = execute_script('return window.innerHeight');
// Error detection
const console_errors = execute_script('return window.__errors || []');
const network_failures = execute_script(`
return performance.getEntriesByType('resource')
.filter(r => r.transferSize === 0 && r.duration > 0)
.map(r => r.name);
`);
const layout_issues = execute_script(`
return document.documentElement.scrollWidth > window.innerWidth
? ['horizontal-overflow']
: [];
`);
return {
name,
url,
screenshot_path,
page_height: height,
viewport_height: viewport,
needs_scroll: height > viewport,
console_errors,
network_failures,
layout_issues,
has_issues: console_errors.length > 0 ||
network_failures.length > 0 ||
layout_issues.length > 0
};
}
エラー処理
スクリーンショットの寸法エラー
fullPage: false を使用しているにもかかわらず寸法エラーが発生する場合、ページで特殊なビューポート設定が使用されている可能性があります。その場合は、代わりにファイルに保存してください。
try {
take_screenshot({ fullPage: false });
} catch (error) {
if (error.includes('8000 pixels')) {
take_screenshot({ fullPage: false, path: './fallback.png' });
}
}
ナビゲーションのタイムアウト
try {
navigate(url);
wait(5000);
} catch (error) {
// Log failure and continue
console.log(`Failed to load: ${url}`);
}
要素が見つからない場合
const exists = execute_script(`return !!document.querySelector('#target')`);
if (!exists) {
take_screenshot({ fullPage: false, path: './missing-element.png' });
// Handle accordingly
}
重要な注意事項
- 寸法エラーを避けるため、常に
fullPage: falseをデフォルトで使用してください - 可能な場合は、API への送信ではなく、ファイルシステムにスクリーンショットを保存してください
- ナビゲーション後は、JavaScript の実行を待ってください(最低 1000ms)
- 壊れやすいセレクター方式ではなく、DOM クエリには execute_script を使用してください
- レスポンシブなアプリケーションでは、複数のビューポートをテストしてください
- 証拠は早めに取得してください。要素の状態が変わる前にスクリーンショットを撮ってください
- スクリーンショットの方法を決める前に、ページの寸法を確認してください
追加のツールカテゴリ
次のフラグを指定すると、追加のツールを有効にできます。
- 拡張機能ツールを使用するには、
--categoryExtensionsフラグを指定します。 - メモリツールを使用するには、
--memoryDebuggingフラグを指定します。
拡張機能のテスト
続行する前に確認してください:拡張機能ツール(
install_extension、list_extensionsなど)は、MCP サーバーの起動時に--categoryExtensionsフラグが指定されている場合にのみ使用できます。これらのツールがツール一覧にない場合は、作業を中止し、MCP サーバーの設定を更新するようユーザーに依頼してください。{ "mcpServers": { "chrome-devtools": { "command": "npx", "args": ["chrome-devtools-mcp@latest", "--categoryExtensions"] } } }更新後、変更を反映するには、ユーザーが MCP サーバー(または AI クライアント)を再起動する必要があります。
- インストール:展開済みの拡張機能へのパスを指定して
install_extensionを使用します。 - 識別:レスポンスから拡張機能 ID を取得するか、
list_extensionsを呼び出して確認します。 - アクションの実行:該当する場合は、
trigger_extension_actionを使用してポップアップまたはサイドパネルを開きます。 - サービスワーカーの確認:
serviceWorkerIdを指定してevaluate_scriptを使用し、拡張機能の状態を確認するか、バックグラウンドアクションを実行します。 - ページ動作の確認:拡張機能が動作するページに移動し、
take_snapshotを使用して、コンテンツスクリプトが要素を挿入したか、ページを正しく変更したかを確認します。