本文へスキップ

ios-webkit-debug-proxy で WKWebView を検査する

📋目次

はじめに

WebKit のブログで、Claude Code のような AI エージェントから Safari を検査できるようにする MCP サーバーが Safari Technology Preview に搭載されたという記事を見かけました。 DOM やコンソールログを読めるという内容だったので、iOS アプリ内の WKWebView も同じ手順で検査できないかと考えました。

調べてみると、この MCP サーバーは safaridriver(Apple 公式の WebDriver 実装)をラップしたもので、操作対象は macOS の Safari タブに限られていました。 iOS アプリに埋め込まれた WKWebView は範囲外です。 代わりに見つけたのが、Google 公式の ios-webkit-debug-proxy(通称 iwdp)です。 この記事では、iwdp を使って WKWebView の DOM や Cookie を検査する方法を紹介します。

ios-webkit-debug-proxy とは

iwdp は、WebKit の Remote Debugging Protocol を HTTP・WebSocket に変換する OSS です。 Chrome DevTools から iOS の Safari や WKWebView をデバッグできるものです。 Homebrew で導入できます。

brew install ios-webkit-debug-proxy
# -c: 9221 番でデバイス一覧を、9222-9322 の範囲でデバイスごとのタブ一覧用ポートを公開する
ios_webkit_debug_proxy -c null:9221,:9222-9322

対象の WKWebView を検査するには、isInspectable = true を設定しておく必要があります。

#if DEBUG
webView.isInspectable = true
#endif

デバイスとタブの一覧を取得する

起動すると、9221 番ポートで接続中のデバイス一覧を返します。

curl http://localhost:9221/json
[{ "deviceId": "...", "deviceName": "iPhone", "url": "localhost:9222" }]

url に対して同じように /json を叩くと、そのデバイス上で inspectable な WKWebView の一覧が返り、各要素の webSocketDebuggerUrl を使って個別のページに接続できます。

curl http://localhost:9222/json
[{ "title": "", "url": "https://example.com/", "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/1" }]

webSocketDebuggerUrl に WebSocket で接続すると、まず Target.targetCreated イベントが届き、対象ページの targetId がわかります。 コマンドはこの targetId を使って Target.sendMessageToTarget でラップして送り、結果は Target.dispatchMessageFromTarget イベントの message フィールドとして非同期に届きます。

import WebSocket from "ws";

const ws = new WebSocket("ws://localhost:9222/devtools/page/1");
let targetId;
let nextId = 1;

ws.on("message", (data) => {
  const msg = JSON.parse(data.toString());

  if (msg.method === "Target.targetCreated" && msg.params.targetInfo.type === "page") {
    targetId = msg.params.targetInfo.targetId;
    const command = { id: nextId++, method: "Page.getCookies" };
    ws.send(JSON.stringify({
      id: nextId++,
      method: "Target.sendMessageToTarget",
      params: { targetId, message: JSON.stringify(command) },
    }));
  }

  if (msg.method === "Target.dispatchMessageFromTarget") {
    const result = JSON.parse(msg.params.message);
    console.log(result.result?.cookies);
  }
});

Page.getCookies を呼ぶと、Cookie の一覧が配列で返ってきます。

[{ "name": "sessionid", "value": "...", "httpOnly": true, "secure": true }]

httpOnly: true の Cookie も値まで取得できます。 document.cookie(JS 経由)では見えないセッション ID などもここに含まれるため、扱いには注意が必要です。

Safari で Web Inspector を開いていると検査できない

macOS の Safari(または Safari Technology Preview)の Web Inspector が同じ WKWebView に既に接続していると、iwdp 経由の WebSocket コマンドは Timed out waiting for page target で失敗します。 タブ一覧を返す /json エンドポイントは正常に応答するため、原因がわかりづらいところです。 Web Inspector のウィンドウを閉じれば解消します(Safari アプリ自体は起動したままで構いません)。

MCP サーバーとしてラップする

ここまでの手順は curl と WebSocket のクライアントコードで完結しますが、Claude Code からその都度呼び出すには手間がかかります。 そこで iwdp を Anthropic 公式の MCP TypeScript SDK でラップし、list_devicesget_cookies のようなツールを持つ MCP サーバーを組み立ててみました。 Claude Code から「WebView の Cookie を見て」と頼むだけで、ここまでの手順を辿ってくれるようになります。

まとめ

Apple 公式の Safari MCP サーバーは macOS の Safari タブが対象で、iOS アプリ内の WKWebView は検査できません。 Google 公式の iwdp を使えば、DOM や Cookie を含めて WKWebView を検査できます。 iOS アプリの WebView 周りを調べる機会があれば、試してみてください。

参考リンク

この記事をシェア