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" }]
Cookie を取得する
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_devices や get_cookies のようなツールを持つ MCP サーバーを組み立ててみました。
Claude Code から「WebView の Cookie を見て」と頼むだけで、ここまでの手順を辿ってくれるようになります。
まとめ
Apple 公式の Safari MCP サーバーは macOS の Safari タブが対象で、iOS アプリ内の WKWebView は検査できません。
Google 公式の iwdp を使えば、DOM や Cookie を含めて WKWebView を検査できます。
iOS アプリの WebView 周りを調べる機会があれば、試してみてください。