🥳

Webサイトの認証をPlaywright MCPに突破させ、認証情報を保持する (Storage State)

に公開

前提

Webサイト開発において、ローカル開発時にもCognitoやらと接続して認証をしているプロジェクトがあり、
そのプロジェクトではCookieやらLocalStorageやらに認証情報を保持しているものとします。
正しい認証情報があれば認証を突破してページにアクセスでき、認証情報がない/不正(expired等) であればログインページにリダイレクトされるイメージです。

こうしたページに対して、AIエージェント(今回はClaude前提で説明します)を使い、アクセスしたくなるシーンがあるわけですが、当然ながら毎回「ログインページが表示されました。ログインを行ってください。」とユーザに要求してきます。
面倒くさいです!!勝手に突破してほしい!!

忙しい人のための結論

これでPlaywrightMCPで使うブラウザのデータを永続化する

  ...
  "mcpServers": {
    "playwright": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@playwright/mcp@latest",
        "--isolated",                        // これ設定する
        "--storage-state=storage-state.json" // これ設定する
      ],
      "env": {}
    }
  }
  ...

永続化した後、そのブラウザでログインする。

色々な解決方法

Playwright MCPのREADMEを読めば分かる話ではありますが、色々と方法があります。
DeepWikiで確認すると尚早いでしょう。
https://github.com/microsoft/playwright-mcp

  • 普段ユーザが使ってるブラウザのプロファイルを利用
    • そのプロファイルに認証情報が保持されているなら今回の問題は解決できる
  • secretsに認証情報を指定
  • Isolated modeで毎回同じStorage Stateを利用
    • 「普段ユーザが使ってるブラウザのプロファイルを利用」に近いです
    • MCP用のプロファイルのストレージをどっかに持っておいて使いまわそう。みたいなイメージ
      • 正確にはプロファイルではないです。もっと遥かに軽量

「普段ユーザが使ってるブラウザのプロファイルを利用」でもいいんですが、精神衛生上あまり健全ではありません。
ということで今回はStorage Stateの方でいきましょう。

Storage Stateを設定しよう

※ ここからはここを読めば済む話ではあります
https://github.com/microsoft/playwright-mcp?tab=readme-ov-file#user-profile

今回のPlaywright MCPのStorage Stateの設定は1プロジェクトに閉じた方がキレイですね。
別プロジェクトでは別のユーザプールの認証情報を保持したいかもしれないしね。

ということでプロジェクト単位でstorage sessionの設定を持てるよう、プロジェクトの .mcp.json に以下を書くのがいいのではと思います。

  ...
  "mcpServers": {
    "playwright": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@playwright/mcp@latest",
        "--isolated",                        // これ設定する!!
        "--storage-state=storage-state.json" // これ設定する!!
      ],
      "env": {}
    }
  }
  ...

設定後はargsがちゃんと効いているのか確認するため、claudeで /mcp コマンドを叩いて確認しておきましょう
Playwright MCP, Claude Code(たぶんセッションでOK) を再起動してから確認するのが良いと思います。

以下のようにArgs, Config locationを確認しておきましょう。

Playwright MCP Server

Status: ✔ connected
Command: npx
Args:-y @playwright/mcp@latest --isolated
    --storage-state=/tmp/storage-state.json
Config location/Users/you/project-name/.mcp.json
Capabilities: tools  
Tools: 22 tools

ついでにスクリプトを書いておこう

前段の作業でStorage Stateの永続化はできたのですが、セッション切れ等を思うと、1日の作業のはじめには改めて認証させて、その認証情報の永続化(Storage Stateのexport)をしておきたいですね。

そのためのスクリプトを作り、必要に応じて都度実行するよう指示しておきましょう。
プロジェクトのCLAUDE.mdか、プロジェクトスコープで作ったagentのmdに書いておくのが良さそうです。

認証画面やそこに至るまでのフローは人それぞれなので、適当にClaudeに書かせればいいと思います。


// メールアドレス入力フィールドを探して入力
const usernameField = await page.$('input[type="email"]');
await usernameField.fill(username);

// パスワード入力フィールドを探して入力
const passwordField = await page.$('input[type="password"]');
await passwordField.fill(password);

// サインインボタンを探してクリック
const submitButton = await page.$('button[type="submit"]');
await submitButton.click();

// 認証状態をJSONにエクスポート
// MCP側の--storage-state=storage-state.jsonの指定に合わせよう
const outputPath = 'storage-state.json';
await context.storageState({ path: outputPath });

usernameやpasswordは .env等 から入力するようにしましょう。
ローカル開発用のユーザプールのデータとはいえ、一応ね。

こうしてJSONでexportしておけば永続化的にはOKです。

大事なデータは忘れずに保護しておく

前段で利用したであろう、 .env
そして トークンやらが平文で書かれた storage-state.json
この辺は忘れずにpermissions.denyに設定しておくと安心

"permissions": {
    "allow": [...],
    "deny": [
      "Read(.env)",
      "Read(storage-state.json)"
    ],
    ...
},

.gitignore にも忘れずにね!

Discussion