出発点:裁断できない本をどう取り込むか
book-knowledge-base には既に「読み解く」スラッシュコマンド(/yomitoku)がある。裁断本をスキャンしたPDFを yomitoku に投げ、章節単位に分割して Turso に格納する流れだ。問題は、最近 Kindle で買った本がこのパイプラインに乗らないこと。Amazon の DRM がかかっていてPDFに落ちないから、裁断本と同じ前処理を踏めない。
そこで「read.amazon.co.jp の Kindle Cloud Reader をスクショで巡回して、画像群を既存パイプラインに流せばいい」という発想に切り替えた。OCRから先は /yomitoku がそのまま使える。前段の「画像を集めるところ」だけを新規で組めばよい。
朝のうちはこのアイデアを温めるだけのつもりだったが、気がついたら半日溶けていた。
採用方針:C案ハイブリッド(スラッシュコマンド × Chrome拡張)
最初に「スラッシュコマンド単体 vs Chrome拡張機能単体 vs ハイブリッド」の3案を並べた。比較した結果、ハイブリッドのC案で進めることにした。
- スラッシュコマンド単体: Chrome DevTools MCP を使えばページめくり・スクショ・OCR 委譲まで一気通貫で書ける。会話で「○ページまで」「OCR込み/抜き」を毎回指示変更できる柔軟さがある。一方で、長時間のページ送りループを MCP セッションに張り付けて回すのは不安定になりがち。
- Chrome拡張機能単体: アイコンクリックで起動、ブラウザ内のDOM操作とスクショに強い。ただし、保存先ディレクトリやページ数の指定をUIに毎回作り込まないと変更できない。
- C案ハイブリッド(採用): ① スラッシュコマンドで起動 → ② Chrome拡張機能が Kindle Reader のページめくりとスクショを担当 → ③ ダウンロードされた画像群を
/yomitokuパイプラインに流して OCR/章節分割/Turso 登録。
C案を選んだのは、動的な指示性(スラッシュコマンド側)とページ操作の安定性(拡張機能側)を両取りできるから。Kindle のページめくりは拡張機能のバックグラウンドに任せて、スラッシュコマンドは前後の段取りだけ見る、という分業にした。
準備:Chrome DevTools MCP が朝から壊れていた
実装に入る前に Chrome DevTools MCP が動かない。mcp__chrome-devtools__* のツールが一切ロードされない。ツール検索しても空振りする。
~/.claude/rules/windows.md の「最頻の詰まり」に該当していた。9222 ポートで curl -s http://localhost:9222/json/version を叩くと壊れた残骸が返ってくる。壊れた残骸の9222リスナーが居座っているのが真因。本来は chrome.exe を全部落として temp profile + 9222 で起動し直し、/mcp で chrome-devtools を reconnect すれば復活するはずだった。
ところがこの日は別の問題も重なっていた。.claude.json から chrome-devtools MCP の登録そのものが消えていた。バックアップ(3/21時点)を覗くと24箇所に書かれていたものが、現在は0件。3/21〜6/17 のどこかで設定ファイルが書き換えられて消えた、というのが正体だった。
仕方ないので claude mcp add で user スコープに再登録。Git Bash の MSYS パス変換で /c が C:/ に化けて起動失敗するトラップにも引っかかったが、修正してリトライ。さらにこの先 .claude.json が消えても気づけるよう、MCP サーバー設定だけ抽出して ~/.claude/mcp-servers-snapshot.json として git 管理に入れた。
Chrome 149 stable で remote debugging を許可する方法も、ログイン済み Chrome に繋ぐために必要だった。chrome://inspect/#remote-debugging で incoming debugging connections を Allow に切り替え、--autoConnect 方式に変更。Claude Code を再起動してようやく mcp__chrome-devtools__* が見えるようになった。
ここまでで午前中が終わった。
プローブ:Kindle Cloud Reader の DOM を覗く
復活した MCP で Kindle のタブに切り替えてスクショを撮ったところ、ちゃんと撮れた。ASIN/タイトル/Location/「Back to 309」(しおり)が DOM から取れることまで確認。
ArrowRight で 20→22 へ進む(+2/ページ)、ArrowLeft で 22→8→2 まで戻せる。先頭 Location 2 まで到達できたので、巡回の最小単位は動くことが分かった。
そこから先で UI ノイズ(「Back to 309」表示、下部スクロールバー)を CSS で隠してテスト撮影。クリーンな状態が取れたので、ここで「5ページ分連続で進めるループ」に入ろうとした矢先、設計議論に戻すことにした。
「ループは MCP セッションで回し続けるより、Chrome 拡張機能のバックグラウンドに任せた方が安定する」と判断したから。C案の本気の実装に切り替えた。
実装:chrome-extension-kindle を新規ディレクトリで切る
C:\Users\numbe\Git_repo\chrome-extension-kindle を新規作成して git init。既存の chrome-extension-MF(クラウド会計)や chrome-extension-x(X/Twitter)と同じ命名規則に揃えた。Chrome 拡張機能は 全て別々のリポジトリで管理 している慣習に乗る形だ。
並列でファイル群を生成させた。manifest.json、popup.html、popup.js、content.js、background.js、offscreen.html/js、アイコン群。スラッシュコマンドは book-knowledge-base 側に /yomitoku-kindle として追加。既存 /yomitoku に画像群を渡すだけのアダプタに留めた。
popup.js の innerHTML を安全な DOM 構築に置き換える等の細かい修正は途中で挟んだが、骨格は数回のターンで揃った。
試行錯誤のフェーズ:5つの壁にぶつかった
ここからが本番で、E2E で動かそうとするたびに別の問題が顔を出した。
壁1: 文字化けと「位置: 不明」
最初に動かした拡張機能は、ページ情報が「位置: 不明」になり、書名も文字化けしていた。原因を Chrome DevTools 経由で直接調査したら、Kindle Cloud Reader 側で UTF-8 → Latin-1 の mojibake が起きていた。TextDecoder で復元できることを確認し、content.js に組み込んで「明治維新とは何だったのか――世界史から考える」相当のタイトルが綺麗に取れるようになった。
壁2: 拡張機能がリストに出てこない
content.js を直してリロードしてもらったが、chrome://extensions/ の拡張機能リストに「Kindle Cloud Reader Capturer」が出てこない。ユーザーが「リロードしたよ」と言ってくれたタイミングと、こちら側で MCP から状態を覗くタイミングがずれていた可能性が高い。
何度もスクショを撮ってもらいながら、最終的にロードできた。「リロード」が拡張機能のリロードなのか Kindle タブのリロードなのか、口頭で曖昧になりやすいことを学んだ。
壁3: Reader did not become ready (slider not found) in 60s
巡回ループに入ると、60秒経って Reader did not become ready (slider not found) in 60s のエラーで止まる。「進んでないんで、ページの画面が多分止まってます」というユーザーの観察が正しかった。
調査したら、対象書籍が 固定レイアウト(fixed layout)書籍 だった。本文が .kg-full-page-img という画像要素として配信されていて、Kindle が "Learning reading speed..." モードに居る間 reader-footer-title が空のまま。slider が出てくる前提のロジックが破綻していた。
ページ送りは「Next/Previous page ボタンを直接クリック」する方式に切り替え、終端判定は画像の fingerprint(同じページが連続したら終端)で組み直した。
壁4: 進捗が見えない
popup を開いても「実行中」とだけ出て、動いているのか止まっているのか分からない。「動いてるのか止まってんのかよくわかりません」という指摘を受けて、popup.js にリアルタイム進捗表示を入れた。ページ番号と取得済み枚数が刻々と更新されるようにして、ユーザーが「進んでない」を画面で判定できるようにした。
壁5: ファイル名が UUID になる + 3枚で落ちる
「3枚今落ちたんすかね」と聞かれて Downloads フォルダを覗いたら、ダウンロード.png という名前のファイルが UUID 付きでばらまかれていた。kindle-captures/<ASIN>/page_NNNN.png の指定が完全に無視されていた。
さらに進めたら今度は URL.createObjectURL is not a function のエラーが popup に一瞬出る。MV3 の service worker から URL.createObjectURL が削除されている仕様にぶつかっていた。専用の Offscreen Document を立てて、そこで blob URL を作る回避策に書き換えた。
ファイル名の方は、blob URL を chrome.downloads.download に渡すと filename 引数が無視される仕様だったので、chrome.downloads.onDeterminingFilename リスナーで強制上書きするように変更。UUID 名で散らばっていた 69 個の PNG を掃除してから、ようやく kindle-captures/<ASIN>/page_NNNN.png の形でサブフォルダに連番保存されるようになった。
着地:v0.2 で「一応うまくいってる」状態
夕方になって、ようやく popup から実行ボタンを押すと、Kindle のページが順番に送られて、Downloads の kindle-captures/<ASIN>/ 配下に page_0001.png から連番で溜まる状態になった。OCR とTurso 登録は明日に持ち越し。
「OK。一応うまくいってるみたいなんで、ここまでの進捗ちょっとドキュメンタリー残しておいてください。また明日やりましょう」で締めて、計画書に今日の格闘記録(5つの壁と解決方法)と拡張機能 v0.2 の最終構成、残課題、明日の復帰プロンプトをまとめて書き残してもらった。
学びメモ
- 「MCPで一気通貫」より「拡張機能に逃がす」が正解だった瞬間が確かにあった。MCP セッションで長時間ループを回し続けると不安定になる。バックグラウンドに任せられる仕事は拡張機能側に分離した方が、観察と再開がしやすい。
- 進捗の可視化を後回しにすると、進んでいるか止まっているかが分からなくなる。popup に進捗表示を入れた瞬間、デバッグの解像度が一段上がった。最初から組むべきだった。
- MV3 の制約は service worker の制約。
URL.createObjectURLが使えない、localStorageが使えない、等の罠が随所にある。Offscreen Document はその回避策として覚えておく。 - Kindle の本には固定レイアウトとリフロー型がある。固定レイアウトは本文が画像として配信されるので、テキスト抽出ではなく OCR 一択になる。今回の対象書籍はたまたま固定レイアウトだったが、リフロー型は別の DOM 取得経路が要る。
.claude.jsonのMCP 設定はバージョン管理されていないので、消えても気づきにくい。今日抽出した~/.claude/mcp-servers-snapshot.jsonを git に入れたので、次に何か消えても git log で追える。
明日やること
- OCR連携: 拡張機能が保存した
kindle-captures/<ASIN>/page_*.pngを/yomitokuに渡して章節分割まで通す - Turso 登録:
book-knowledge-baseの既存スキーマに乗せて、Kindle由来かPDF由来かを区別するフラグを追加する - リフロー型書籍での挙動を別の本で1冊試す(固定レイアウトしかテストできていない)
- スラッシュコマンド
/yomitoku-kindle <URL>から拡張機能起動 → 完了通知 → OCR まで自律的に連結する部分の検証