Claude Code Claude Code MCP Playwright

Claude CodeからPlaywright MCPを使って、自己署名証明書で動いているローカルのHTTPS開発サイトのスクリーンショットを撮ろうとしたら、net::ERR_CERT_AUTHORITY_INVALIDで開けませんでした。playwright-coreパッケージとインストール済みのChromeを使う短いスクリプトに切り替えて回避した記録です。

発生したエラー

Playwright MCPのbrowser_navigateでローカル開発サイトへアクセスすると、次のエラーで止まります。

Error: browserBackend.callTool: net::ERR_CERT_AUTHORITY_INVALID at https://dev-site.local/
Call log:
  - navigating to "https://dev-site.local/", waiting until "domcontentloaded"

ローカル開発環境は自己署名の証明書でhttps://〜.localを動かしているため、ブラウザが「信頼できない証明書」として接続を拒否しています。

MCPのツール呼び出しからは証明書エラーを無視できない

Playwright自体にはignoreHTTPSErrorsというオプションがあり、ブラウザコンテキストの生成時に渡せば自己署名証明書でも接続できます。ただしMCP経由の操作ではコンテキストの生成をMCPサーバー側が行うため、ツール呼び出しのパラメータからこのオプションを渡す手段がありません。今回はClaude Codeのプラグインとして導入したPlaywright MCPを使っていて、サーバーの起動オプションに手を入れるのも大げさだったので、スクリーンショット取得だけ別の手段に切り替えました。

playwright-coreとインストール済みChromeで撮る

作業用ディレクトリでplaywright-coreをインストールします。

npm install playwright-core

playwright-coreはブラウザ本体をダウンロードしない軽量パッケージです。通常のplaywrightパッケージだと専用ブラウザのダウンロードが走りますが、channel: 'chrome'を指定すればマシンにインストール済みのGoogle Chromeをそのまま使えるので、セットアップが一瞬で終わります。

実際に使ったスクリプトがこちらです。PC(幅1280px)とスマホ(iPhone 13相当)の2パターンをフルページで撮ります。

// ローカルHTTPSサイトのスクリーンショット取得スクリプト
const { chromium, devices } = require('playwright-core');

(async () => {
  // インストール済みのGoogle Chromeを使う(ブラウザのダウンロード不要)
  const browser = await chromium.launch({ channel: 'chrome', headless: true });

  // PC (幅1280px)
  const pcCtx = await browser.newContext({
    ignoreHTTPSErrors: true,  // 自己署名証明書のエラーを無視する
    viewport: { width: 1280, height: 900 },
    deviceScaleFactor: 2,     // Retina相当の解像度で撮る
  });
  const pc = await pcCtx.newPage();
  await pc.goto('https://dev-site.local/', { waitUntil: 'networkidle' });
  await pc.screenshot({ path: 'screen_pc.png', fullPage: true });
  await pcCtx.close();

  // スマホ (iPhone 13相当のビューポート・UA)
  const spCtx = await browser.newContext({
    ...devices['iPhone 13'],
    ignoreHTTPSErrors: true,
  });
  const sp = await spCtx.newPage();
  await sp.goto('https://dev-site.local/', { waitUntil: 'networkidle' });
  await sp.screenshot({ path: 'screen_sp.png', fullPage: true });
  await spCtx.close();

  await browser.close();
})().catch(e => { console.error(e); process.exit(1); });

ポイントは3つです。

  • ignoreHTTPSErrors: true はコンテキスト単位で指定する(これが今回の本題)
  • channel: 'chrome' でインストール済みChromeを使うため、ブラウザのダウンロードが不要
  • devices['iPhone 13'] を展開すればビューポートやユーザーエージェントごとスマホ表示になる

このスクリプトでPC・スマホ両方のフルページスクリーンショットが問題なく撮れました。

MCPで足りない部分はスクリプトで補う

日常のブラウザ操作はPlaywright MCPで十分ですが、今回のようにコンテキスト生成時のオプションが必要な場面では、playwright-coreの短いスクリプトを書いてしまうほうが早いです。スクリプトの作成と実行自体もClaude Codeにそのまま任せられるので、会話の流れを止めずに済みます。