poltertab について
PolterTabは、ログイン済みのChromeプロファイルをAIエージェントが操作・読み取りできる、ローカルMCPサーバーとChrome拡張機能です。ページ操作、構造化スクレイピング、ネットワークデータの取得、タブセッション管理に対応します。
主な機能
- 01既存のChromeプロファイルを操作
- 02ページの移動、クリック、入力、スクロール
- 03複数ページから構造化レコードを抽出
- 04ネットワークのJSONレスポンスを取得
- 05名前付きセッションでタブを管理
活用シーン
- 01ログイン済みサイトの作業を自動化
- 02ページ分割されたレコードを収集
- 03仮想化されたページのデータを調査
MCP 対応
PolterTabはstdioでMCPクライアントに接続し、ローカルサーバーからブラウザ操作ツールを提供します。サーバーとChrome拡張機能はローカルWebSocketで通信します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
28掲載時のツール一覧 · 3 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| url | string | はい | |
| tabId | number | いいえ | このタブ(browser_tab_list の ID)を現在のタブにせず操作します。省略すると、このエージェントの現在のタブ、つまり最後に移動、開く、または切り替えたタブを使用します。Chrome に存在しない tabId を指定すると tab_not_found が返されます。 |
| session | string | いいえ | 実行対象の名前付きセッション(タブ)。これが現在のタブになります。新しい名前で browser_navigate を呼び出すと、そのセッション専用のタブが開くため、ループで何百ものタブを開かずに、1 つのタブを使い続けられます。その名前のセッションがまだ存在しない場合、他のツールはエラーになります。 |
詳細
PolterTab — あらゆる AI のためのブラウザー操作
すでにログインしている Chrome を、あらゆる AI エージェントから使えるようにします。 PolterTab は Chrome 拡張機能と、ローカルの MCP(Model Context Protocol)サーバーです。
Chrome 拡張機能と Model Context Protocol(MCP)サーバーです。AI は、普段使っているブラウザー内で動作します。実際のプロフィール、Cookie、ログイン済みのセッションを利用できます。拡張機能をインストールし、MCP クライアントからサーバーに接続するだけで、Claude Desktop、Cursor、その他あらゆる MCP 対応エージェントで使えます。
PolterTab を使う理由
- 実際のプロフィール — すでにログインしている Chrome 上で動作します。すべてのサービスからログアウトされた、新しいヘッドレスブラウザーを使う必要はありません。
- 複雑なセットアップは不要 — Chrome ウェブストアから拡張機能を追加し、MCP エントリーを 1 つ追加するだけです。
- あらゆる AI ツールに対応 — MCP 対応クライアントなら、どれでも接続できます。
仕組み
Any MCP Agent (Claude Desktop, Cursor, custom agents)
│ Stdio (MCP Protocol)
▼
Node.js MCP Server (mcp-server/index.js)
│ WebSocket (port 7822 by default)
▼
PolterTab Chrome Extension
│ Chrome APIs + DOM
▼
Your existing Chrome profile
複数のエージェントが同時に同じブラウザーを指定できます。最初に WebSocket ポートを確保したサーバーが拡張機能に対応し、残りのサーバーはそのサーバーを経由します。複数のエージェントを同時に実行するをご覧ください。
お使いのマシンから外部に送信される情報
PolterTab はすべてお使いのマシン上で動作します。PolterTab のサーバー、アカウント、テレメトリーはありません。
- MCP サーバーはローカルで動作します。 stdio を介して AI クライアントと通信し、拡張機能が使用する WebSocket は、このマシン上(デフォルトでは
127.0.0.1および::1、ポート 7822)のみで待ち受けます。サーバーはウェブページからの接続を拒否します。ブラウザーからの接続は、Chrome 拡張機能(chrome-extension://)のオリジンからでなければなりません。また、接続を維持したり、アップロード設定を変更したり、ログを読み取ったりできるのは、Chrome ウェブストア版(自動的に信頼されます)か、ペアリング済みの拡張機能だけです。(アーキテクチャ) - ページの内容が送られるのは、エージェントが送信する先だけです。 PolterTab は、読み取ったりスクレイピングしたりした内容を MCP クライアントに返します。クライアントは、その内容をお客様が設定したモデルプロバイダーに転送します。PolterTab 自体がページの内容を外部に送信することはありません。
- フォルダーを許可するまで、ファイルのアップロードは無効です。
browser_upload_fileは、poltertab uploads allow <dir>でフォルダーを追加するまで、すべてのパスを拒否します。機密性の高い場所は常にブロックされ、許可リストに追加することはできません。現在の一覧を確認するにはpoltertab uploadsを実行してください。 - npm の来歴情報。 リリースは
npm publish --provenanceを使って公開されます。これにより npm には、公開された tarball と、それを生成した GitHub Actions ビルドとの間の、署名付きで検証可能な関連情報が記録されます。 - 例外は 1 つ — バージョン確認です。 実行中のサーバーは、npm のバージョンを 1 日 1 回確認するために、外部へのリクエストを 1 回行います(
registry.npmjs.org)。さらにpoltertab setupは、Chrome ウェブストアのバージョンを一度だけ確認します(clients2.google.com)。どちらも、サーバーと拡張機能のバージョン不一致を警告するための比較のみを行い、ページの内容や個人データは送信しません。両方ともPOLTERTAB_NO_UPDATE_CHECK=1で無効にできます。
1.12.0 以降、 ブラウザーを操作できるのは、Chrome ウェブストア版の拡張機能か、ペアリング済みの拡張機能だけです。パッケージ化されていない拡張機能は、
poltertab uploads pairで一度ペアリングしてください。
脆弱性を報告するには、SECURITY.mdをご覧ください。
セットアップ
Node 18 以降が必要です。
1. インストーラーを実行する
npm install -g poltertab
poltertab setup
ウィザードで、すべてのプロジェクトにインストールするか、現在のプロジェクトだけにインストールするかを選択します。 その後、以下の3つを配置します。
browser-navigation-strategyスキル。エージェントが手ごわいブラウザーを操作する方法を把握できますCLAUDE.mdセクション。ツールが利用可能であることを認識できるようにしますclaude mcp addによる MCP サーバーの登録
安全に再実行できます。各手順では実施済みの作業を検出するため、アップグレード時や再実行時に重複することはありません。
グローバルへのインストールを避けたい場合は、npx poltertab setup でも同じ操作を行えます。
2. Chrome Extension をインストールする
Chrome ウェブストアから Chrome に追加 します。Chrome はストアの拡張機能を自動で最新の状態に保つため、拡張機能自体を開発している人以外は、この方法でインストールしてください。
新しいツールを読み込ませるため、AI ツールを再起動してください。
または、展開済みの拡張機能を読み込む(開発者向け/オフラインの場合)
拡張機能を変更する場合や、ウェブストアにアクセスできない場合に使用してください。 展開済みの拡張機能は自動更新されないため、新しい zip を入手したら自分で再読み込みする必要があります。
- 最新のリリース zipをダウンロードし、専用のフォルダーに解凍します(例:
unzip poltertab-extension-vX.zip -d poltertab-extension。macOS の場合はダブルクリックするとフォルダーが自動的に作成されます) - Chrome を開き、
chrome://extensions/にアクセスします - Developer mode(右上のトグル)を有効にします
- Load unpacked をクリックし、そのフォルダー(
manifest.jsonが含まれているフォルダー)を選択します - ブラウザーを操作できるように、一度ペアリングします。
poltertab uploads pairを実行し、拡張機能に表示された4文字のコードを入力してください。(ストアからインストールした場合は自動的に信頼されるため、この手順は不要です。)
その他の MCP クライアント
ウィザードは Claude Code を対象としています。ほかの MCP クライアントでも、poltertab を stdio コマンドとして登録すれば使用できます。
{
"mcpServers": {
"poltertab": {
"command": "poltertab"
}
}
}
Cursor をお使いですか? ワンクリックでインストールできます(上記の stdio エントリーが追加されます)。
npm ではなくクローンから実行する場合は、クライアントにファイルを直接指定してください。
{"command": "node", "args": ["/absolute/path/to/poltertab/mcp-server/index.js"]}
対応している MCP ツール
サーバーは、LLM に28個のツール(すべて browser_ で始まります)を公開します。ページを操作する各ツールでは、特定のタブを指定するためにオプションの tabId と session も使用できます。どちらも省略すると、PolterTab はエージェントの現在のタブを使用します。これは、最後に移動、開く、または切り替えたタブです。最初の browser_navigate(および新しい各セッションの最初の browser_navigate)では、表示中のタブを乗っ取るのではなく、新しいタブを開きます。
ページ操作
| 操作 | パラメーター | 説明 |
|---|---|---|
browser_navigate | url(必須) | URL に移動します |
browser_click | selector(必須) | 要素をクリックします(CSS/XPath/テキスト) |
browser_fill | selector、value(必須)、submit | 入力フィールドに値を入力します。必要に応じてフォームを送信します |
browser_hover | selector(必須) | 要素にカーソルを合わせます |
browser_scroll | direction(必須)、amount、selector | ページまたは要素をスクロールします — up/down/left/right/top/bottom |
browser_smart_scroll | direction(必須)、amount | スクロールした後、遅延読み込みのネットワークデータが届くまで2秒待機します |
ページの読み方
ここにあるすべてのツールは output_file を受け取り、ペイロードを
~/.poltertab/downloads/ に書き込み、要約のみを返します。要約には、行数、フィールド名、
充足率、サンプルレコード2件が含まれます。ざっと見るだけの場合を除き、これを使ってください。生のペイロードを
コンテキストウィンドウに取り込む方法をデフォルトにしてはいけません。
| アクション | パラメーター | 説明 |
|---|---|---|
browser_extract | record、fields(必須)、anchor、max_text、probe、output_file | レコードごとにフィールドをまとめた繰り返しレコードです。下記を参照してください |
browser_extract_all | url_template、record、fields(必須)、key、limit、offset、start_page、max_pages、fill_tolerance、output_file | ページごとにモデルとの往復を行わず、1回の呼び出しでページネーションと抽出を実行します |
browser_scrape | selector、attribute、multiple、fields、max_text、output_file | 指定した要素、またはページ全体をスクレイピングします。attribute には text のほか、任意の属性名を指定できます。href/src は絶対URLで返されます。fields でページ全体のスクレイピング結果から返す部分を選べます。["meta","jsonld"] を指定すると、本文テキスト50KBを取得せずに og: タグと schema.org のデータを取得できます |
browser_snapshot | interactive_only、max_nodes、max_depth、output_file | 表示中および操作可能なノードを ref タグ付きのツリーで返します。最大400件です |
browser_get_text | selector(必須)、max_text、output_file | 1つの要素のテキストコンテンツです。テキストが切り詰められた場合、結果にフラグを付けます |
browser_get_title | — | ページタイトルとURL |
browser_get_url | — | ページURLとタイトル |
browser_screenshot | — | 表示中のタブをbase64 PNGで取得します(タブにフォーカスします) |
レコードの抽出
browser_scrape はフラットなリストを返すため、どの値がどのレコードに属するのかが分からなくなります。要素が1つなら問題ありませんが、90件では危険です。フィールドが任意項目になった途端、名前と電話番号をフラットにスクレイピングすると、後続の電話番号が1行ずつずれ、ページ内の残りのデータも誤って割り当てられます。
browser_extract はレコードのコンテナを受け取り、各フィールドをその内部で解決します。
{
"record": ".agent-card",
"fields": {
"name": { "sel": "a.agent-card-name", "get": "text" },
"url": { "sel": "a.agent-card-name", "get": "href" },
"phone": { "sel": "a[href^='tel:']", "get": "href", "strip": "tel:" },
"socials": { "sel": "a.social-button", "get": "href", "many": true }
},
"anchor": "url",
"output_file": "agents.csv"
}
- フィールドが見つからない場合は
nullが返ります。 位置がずれることはありません。 selはレコードのルートを基準とします。ルート自体を指定するには、省略するか"."を使用してください。getに指定できるのはtext(デフォルト)、href、src、または任意の属性名です。anchorには、実際のレコードに必ず存在するフィールドを指定します。このフィールドがないレコード(一覧の最終ページの空きを埋めるプレースホルダーカードなど)は除外され、nullだけの行として出力されるのではなく、droppedに件数が記録されます。
結果には処理内容が示されるため、空の列を回答として見過ごすことはありません。
{ "count": 12, "dropped": 0,
"fill_rates": { "name": 12, "phone": 10, "socials": 0 },
"warnings": ["socials: 0/12 within record scope, but 40 matches page-wide
for a.social-button — record boundary likely too narrow"] }
この警告が、範囲を広げるプローブです。値がすべて空になったフィールドは、ページ全体を対象に再確認されます。レコードに見えるコンテナから、フィールドの一部を含む兄弟要素が除外されていることがよくあるためです。「ソーシャルアカウントなし」と表示されてしまうより、「セレクターの範囲が間違っている」と分かるほうが重要です。
browser_extract_all は同じ仕様と {page} を含む url_template を受け取り、ループを自動で実行します。key で重複を除外し、次のいずれかの条件に最初に達した時点で停止します。
limit_reached、empty_page、duplicate_page(レコードが以前のページと重複するページ。未認識のページサイズパラメーターを無視するサイトで発生します)、fill_rate_deviation(最初のページの基準値と比べて充足率が急落するページ。1ページ目で学習した仕様が10ページ目でひそかに機能しなくなる場合に発生します)、または max_pages です。どの条件で停止したかは必ず報告され、その時点までに収集したデータはすべて返されるため、停止しても実行結果が失われることはありません。
.csv および .jsonl の出力ファイルは、それぞれの形式で書き込まれます。
ネットワークのキャプチャ
DOM が難読化または仮想化されているサイトでは、存在しない可能性のある要素をスクレイピングするのではなく、UI を動かしている JSON を読み取ります。
| アクション | パラメーター | 説明 |
|---|---|---|
browser_set_intercept_patterns | patterns(必須) | キャプチャする URL の部分文字列。例:["graphql", "/api/v1/"]。デフォルトは ["graphql", "/api/", "voyager", "feed"] です |
browser_get_network_state | clear、output_file | タブでキャプチャした生の JSON です。output_file を指定すると ~/.poltertab/downloads/ に書き込み、パスのみを返します。これにより、大きなペイロードがコンテキストウィンドウを圧迫しません |
セッション
セッションは、名前付きのタブです。各エージェントに専用のセッションを割り当てると、複数のエージェントが同じタブを取り合うのを防げます。閉じたタブは、次回使用時に保存済み URL から再作成されます。
| アクション | パラメーター | 説明 |
|---|---|---|
browser_session_create | name(必須)、url、tabId | セッションを作成するか、開いているタブを引き継ぐか、アクティブなタブにバインドします |
browser_session_switch | name(必須) | セッションをアクティブにし、タブが閉じている場合は復元します |
browser_session_list | — | すべてのセッションと、それぞれの状態(alive、recoverable、expired)を表示します |
browser_session_close | name(必須)、force | セッションとそのタブを閉じます。引き継いだタブでは needs_user_permission が返されます。ユーザーに確認してから force: true で再試行してください。 |
browser_session_context | — | 現在のタブの ID、URL、タイトル、セッション、または closedTabId を返します |
タブ
1 つのエージェントで複数のタブを操作できます。各エージェント(および各セカンダリサーバー)には、それぞれ独自の現在のタブがあります。tabId/session を指定しないページ操作ツールは、そのタブで動作します。明示的に tabId を指定すると、現在のタブを変更せずにそのタブを操作します。Chrome に存在しない tabId を指定すると、これを受け取るすべてのツールで tab_not_found が返されます。現在のタブが閉じている場合、対象を指定しない呼び出しは、別のタブでひそかに動作するのではなく、閉じたタブの名前を示すメッセージとともに失敗します。
| アクション | パラメーター | 説明 |
|---|---|---|
browser_tab_new | url、session、background | タブを開き、現在のタブにします |
browser_tab_list | all | PolterTab のタブ(またはすべてのタブ)を表示し、現在のタブを示します |
browser_tab_switch | tabId または session、focus | 別のタブを現在のタブにします。Chrome に存在しないタブを指定すると tab_not_found が返されます。 |
browser_tab_close | tabId または session、force | タブを閉じます(デフォルト:現在のタブ)。PolterTab が開いていないタブ(browser_session_create({tabId}) で引き継いだタブを含む)では needs_user_permission が返されます。ユーザーに確認してから force: true で再試行してください。Chrome に存在しないタブを指定すると tab_not_found が返されます。 |
ファイルのアップロード
| アクション | パラメーター | 説明 |
|---|---|---|
browser_upload_file | selector(必須)、paths(必須)、method("picker" または "drop")、tabId、session | ローカルファイルをページにアップロードします。method: "picker"(デフォルト)では、selector をクリックし、CDP 経由で OS のファイル選択ダイアログをインターセプトします。<input type="file"> またはファイル選択ダイアログを開くボタンであれば動作します。method: "drop" では、DataTransfer のドラッグ&ドロップイベントをディスパッチします。ドロップゾーンで使用してください。パスは ~/.poltertab/config.json の upload_allowed_paths に記載されたディレクトリ内である必要があります。ピッカーでのアップロード中は、短時間のデバッグバナーが表示されます(CDP の要件)。 |
設定 — browser_upload_file を使用する前に、~/.poltertab/config.json に upload_allowed_paths を追加します。
{
"upload_allowed_paths": ["/Users/you/Documents", "/Users/you/Downloads"]
}
許可リストにかかわらず、次のパスは常にブロックされます:~/.ssh、~/.aws、~/.gnupg、~/.config、/etc、/private/etc、/System、/private/System、/Library、/private/Library、/proc、ホームディレクトリ内のドットファイル。注:/tmp(および macOS における実際のパス /private/tmp)はブロックされておらず、通常どおり upload_allowed_paths に追加できます。
サイトメモリ
| アクション | パラメーター | 説明 |
|---|---|---|
browser_get_site_memory | hostname(または domain) | ドメインについて記録された障害と修正 |
browser_save_site_memory | hostname(または domain)、obstacle、solution | サイトで発生した問題と解決方法を記録します |
セレクターの解決
セレクターは次の順序で解決されます。
- スナップショット参照 —
browser_snapshotが返す@e12。スナップショットが記述した正確なノードに解決され、生成されたクラスチェーンより優先されます。 - CSS セレクター —
#id、.class、div > span - XPath —
//div[@class="foo"] - テキスト一致 — 要素のテキストコンテンツとの完全一致
4 つすべてで見つからなかった場合は、シャドウルートの検索(オープンルート、1 階層)とトップレベルの同一オリジン iframe の検索を追加して再試行します。ネストされた iframe(iframe 内の iframe)とクロスオリジン iframe はサポートされていません。その場合、ツールは明確なエラーを返します。
トラブルシューティングとオプション
複数のエージェントを同時に実行する場合:
最初にポート 7822 にバインドした MCP サーバーがプライマリとなり、拡張機能への接続を所有します。後から起動したサーバーはポートが使用中であることを検知し、セカンダリモードに切り替わってプライマリ経由でコマンドをプロキシするため、追加設定なしで複数のエージェントが 1 つのブラウザーを共有できます。プライマリは各セカンダリのコマンドにその ID を付け、拡張機能はエージェントごとに個別の現在のタブを保持するため、エージェントはそれぞれ独自のタブを使用できます。最大 POLTERTAB_MAX_SECONDARIES 個の v2 セカンダリを受け入れます(デフォルトは 50)。プライマリが終了すると、セカンダリの 1 つが昇格して置き換わります。拡張機能のポップアップには、接続中のエージェントが表示されます。
1 つのブラウザーを共有できるエージェント数:
最大 50 個の v2 セカンダリ(プロセスごとに 1 つ)とプライマリが、1 つのブラウザーを共有できます。POLTERTAB_MAX_SECONDARIES で上限を引き上げたり、引き下げたりできます。POLTERTAB_IDLE_EVICTION_MS の期間(デフォルトは 5 分)アイドル状態のエージェントは、スロットを空けるためにクローズコード 4001 で削除されます。次にコマンドを送信すると自動的に再接続するため、エージェントからは削除が見えません。メジャーバージョンがプライマリと一致しないエージェントは、クローズコード 4002 で拒否されます。下記のアップグレードパスを参照してください。
コマンドキュー:
プライマリは、拡張機能に一度に送信するコマンド数を制限します(POLTERTAB_MAX_CONCURRENCY、デフォルトは 6)。この上限に達すると、v2 セカンダリのコマンドはセカンダリごとのキューに入れられます(最大 POLTERTAB_QUEUE_DEPTH スロット、デフォルトは 3)。呼び出し元にコマンドが失われず保留中であることを知らせるため、キューに入ったコマンドは {"type":"queued","id":"...","position":N} ですぐに確認応答されます。v2 セカンダリは、この確認応答を受け取ったときと、コマンドがキューを離れた際の {"type":"dispatched","id":"..."} を受け取ったときに、35 秒のタイムアウトを再設定します。そのため、キューでの待ち時間が実行時間の予算を消費することはありません。セカンダリごとのキューがすでに満杯の状態で届いたコマンドは、[queue_full action=X] として即座に拒否されます。プライマリ自身の直接コマンドも、同じ上限のもとでキューに入れられます。呼び出し元の 35 秒の予算が尽きそうになると、キューに入ったコマンドは [queue_timeout action=X] として破棄されます(2 秒の余裕を設け、呼び出し元側のタイマーより先に破棄されるようにしています)。POLTERTAB_QUEUE_TIMEOUT_MS(デフォルトは 60 秒)は、キューから取り出されないコマンドを対象とする独立した GC の安全策です。キューでの待ち時間を延長するものではありません。
/status エンドポイント:
GET http://127.0.0.1:7822/status は、プライマリのキュー状態、接続中のエージェント、待ち時間のパーセンタイル(p50/p95/p99)の JSON スナップショットを返します。ループバック接続元(127.0.0.1、::1、または ::ffff:127.0.0.1)および Host ヘッダーに localhost またはループバックアドレスが指定されたリクエストに制限されており、それ以外には 404 が返されます。
拡張機能の再接続:
Chrome 拡張機能は、ブリッジサーバーの再起動時や WebSocket の切断時に自動的に再接続します。切断後すぐに接続を試み、その後は 1 秒、2 秒、4 秒……と最大 30 秒まで待機時間を延ばします。スケジュールの途中で停止した場合にサービスワーカーを起動するアラームも備えています。再接続中にコマンドを実行すると、次のように返されます。
[extension_reconnecting port=7822 elapsed=Xs]— 拡張機能は切断されており、再接続中です。少し待ってから再試行してください。[extension_never_connected port=7822]— このサーバーインスタンスには、拡張機能が一度も接続していません。拡張機能がインストールされ、有効になっており、正しいポートを指定していることを確認してください。
クローズコード:
| コード | 意味 | エージェントの動作 |
|---|---|---|
| 4001 | アイドル時の接続解除 — エージェントが POLTERTAB_IDLE_EVICTION_MS の間応答しませんでした | セカンダリは次のコマンド時に遅延再接続します。対応は不要です |
| 4002 | バージョン不一致 — メジャーバージョンがプライマリと互換性がありません | セカンダリは再起動するまで再試行を停止します。すべてのセッションで同じメジャーバージョンが実行されるよう、npm パッケージを更新してください |
アップグレード手順(1.x → 1.8):
PolterTab 1.8 では、バージョンハンドシェイクが導入されます。プライマリとメジャーバージョンが一致しないセカンダリは、クローズコード 4002 を受け取り、再試行を停止します。npm パッケージを更新し、すべてのセッションで同じメジャーバージョンが実行されるようにすると解決します。また、PR-4 の再接続動作を利用するため、Chrome 拡張機能も同時に更新してください。アップグレード前に poltertab doctor を実行して、バージョンの不一致を確認してください。アップグレードしていない 1.7.x のセカンダリは、ハンドシェイクに対応していないため 4002 を受け取りません。バージョン管理されないレガシーセカンダリとして引き続き動作し、コマンドキューをバイパスし、アイドル時の接続解除もされません。
環境変数:
| 変数 | デフォルト値 | 説明 |
|---|---|---|
POLTERTAB_MAX_SECONDARIES | 50 | 接続を受け入れる v2 セカンダリの最大数 |
POLTERTAB_IDLE_EVICTION_MS | 300000 (5 min) | v2 セカンダリが 4001 で接続解除されるまでのアイドル時間 |
POLTERTAB_MAX_CONCURRENCY | 6 | 拡張機能のコマンド同時実行数の上限 |
POLTERTAB_QUEUE_DEPTH | 3 | [queue_full] が返されるまでのセカンダリごとのキュー深度 |
POLTERTAB_QUEUE_TIMEOUT_MS | 60000 (60 s) | キューに滞留したままのコマンドに対する GC の安全策(キューの待ち時間は延長されません) |
POLTERTAB_COMMAND_TIMEOUT_MS | 35000 (35 s) | コマンドごとの制限時間です。拡張機能の 30 秒のナビゲーション待機時間と 500 ms の安定待機時間を超える必要があります。テスト時のみ調整してください |
WebSocket ポートの変更:
7822 をすでに使用しているものが PolterTab 以外にある場合のみ必要です。PolterTab サーバーは設計上このポートを共有します(上記参照)。両側を変更する必要があります。
-
Chrome で拡張機能のアイコンをクリックし、設定を選択します。
-
WebSocket ポートを空いているポート(例:
7824)に変更し、保存をクリックします。拡張機能はすぐに再接続するため、再読み込みは不要です。 -
新しいポートを渡すように MCP サーバーの設定を更新します。
- 環境変数を使う場合:
MCP_BROWSER_WS_PORT=7824 node index.js - CLI 引数を使う場合:
node index.js --port 7824 - Claude Desktop の設定の場合:
"args": ["/absolute/path/to/poltertab/mcp-server/index.js", "--port", "7824"] - 環境変数を使う場合:
DevTools を開いている間にピッカーでのアップロードが失敗する:
Chrome では、タブごとに同時に使用できるデバッガーは 1 つだけです。対象のタブで DevTools が開いていると、browser_upload_file(メソッド "picker")は「Another debugger is already attached」というエラーで失敗します。ピッカーでアップロードする前に、そのタブの DevTools を閉じてください。
debugger 権限を追加すると、拡張機能の再承認が必要になります:
debugger 権限を追加した後に拡張機能のフォルダーを読み込む、または再読み込みすると、Chrome から再承認を求められます。chrome://extensions/ の警告ダイアログで Keep または Allow をクリックするまで、拡張機能は無効になります。展開して読み込んだ拡張機能は自動更新されないため、これは拡張機能のフォルダーを明示的に再読み込みまたは更新した場合にのみ発生します。
拡張機能が接続されない場合:
- MCP サーバーが起動しており、正しいポートを指定していることを確認してください。
chrome://extensions/から拡張機能を再読み込みしてください。
コマンドがタイムアウトする/制限付きページ:
- Chrome でアクティブなタブを開いておいてください。
- Chrome 拡張機能は、
chrome://URL、Chrome ウェブストア、一部の制限されたページとはやり取りできません。この場合、MCP サーバーはエージェントに「このページとはやり取りできません」と適切に返します。
プロジェクト構成
poltertab/
├── package.json # Published npm package (deps + bin)
├── bin/
│ ├── poltertab.js # Entry: bare = MCP server, `setup` = wizard
│ └── setup.js # Installer (skill, CLAUDE.md, MCP registration)
├── skills/
│ └── browser-navigation-strategy/ # Shipped skill, installed by the wizard
├── assets/
│ └── claude-md-snippet.md # The CLAUDE.md section the wizard appends
├── mcp-server/
│ ├── index.js # MCP server (stdio) + WebSocket hub
│ └── test/run.js # Extension + server regression suite
├── test/
│ └── setup.test.js # Installer regression suite
├── chrome-extension/
│ ├── manifest.json # MV3 manifest
│ ├── background.js # WebSocket client, session manager, command router
│ ├── content_script.js # DOM extractor + action executor (isolated world)
│ ├── interceptor.js # fetch/XHR capture (main world)
│ ├── popup.html/js # Connected-agents UI
│ ├── options.html/js # Port configuration UI
│ └── icons/
└── README.md
最新の状態を保つ
poltertab doctor
インストール済みのバージョン、npm に新しいバージョンがあるかどうか、そして重要な点として、2 つの構成要素のバージョンが一致しているかどうかを報告します。
server 1.1.0
extension 1.0.0 SKEW last seen 3m ago
bridge listening on port 7822
state ~/.poltertab
npm 1.2.0 available
npm パッケージは、npm update -g poltertab を実行すると更新されます。Chrome ウェブストアからインストールした拡張機能は、他のストア拡張機能と同様に自動更新されます。読み込んだ unpacked 拡張機能は自動更新されません。Chrome が自動更新するのは、ウェブストアから入手したものだけです。そのため、問題になるのは更新の欠落ではなく、バージョンの不一致です。新しいサーバーが、古い拡張機能では実装されていないコマンドを送信した場合や、Chrome が拡張機能を更新した一方で、まだ npm update を実行していない場合に発生し、要素が不可解にも見つからないという問題として表面化します。
2 つの構成要素には同じバージョンが付与されるため、不一致は明確に判別できます。拡張機能は接続時に自身のバージョンを報告し、サーバーはそれを比較してログに記録し、拡張機能のポップアップに表示します。どちらかが古い場合、セッション中の最初のツール応答で一度だけ通知されるので、自分で確認することを意識しなくても状況がわかります。
更新の確認は、1 日に最大 1 回 registry.npmjs.org にアクセスし、~/.poltertab/update-check.json にキャッシュされます。また、処理をブロックすることはありません。POLTERTAB_NO_UPDATE_CHECK=1 を設定すると確認を無効にできます。バージョンの不一致検出はローカルで行われるため、どちらの場合も引き続き機能します。
poltertab doctor はバージョンの不一致があるとゼロ以外のコードで終了するため、CI やシェルのプロンプトから対応できます。
データの保存場所
サーバーが蓄積するデータは、パッケージ内には保存されません。
~/.poltertab/
├── navigation_memory/ # Per-domain obstacles and fixes (browser_save_site_memory)
└── downloads/ # output_file payloads from any read tool
これはグローバルに npm をインストールする場合に重要です。パッケージは node_modules/ に置かれるため、コードの隣に書き込まれたものは次回の npm update -g で削除されます。サイトのメモリーはアップグレードのたびに記憶喪失のようになり、取得したデータは見つけることのない場所に埋もれてしまいます。
POLTERTAB_HOME を設定すると、ツリー全体の保存先を変更できます。メモリーが mcp-server/navigation_memory/ に保存されていたバージョンからアップグレードする場合は、初回起動時にデータが引き継がれます。移行先に既存のメモがある場合は、常にそちらが優先されます。
リリース
公開は GitHub Releases によって行われます。npm のチャンネルはバージョン文字列で決まるため、正しく設定する必要があるのは git タグだけです。
| バージョン | npm タグ | インストール方法 |
|---|---|---|
1.2.0 | latest | npm install -g poltertab |
1.2.0-rc.1 | rc | npm install -g poltertab@rc |
1.2.0-beta.1 | beta | npm install -g poltertab@beta |
1.2.0-alpha.1 | alpha | npm install -g poltertab@alpha |
リリースを作成するには、次の手順を実行します。
npm version 1.2.0-beta.1 # bumps package.json, syncs the manifest, tags
git push --follow-tags
gh release create v1.2.0-beta.1 --generate-notes --prerelease
npm version は scripts/sync-manifest-version.js を実行し、chrome-extension/manifest.json のバージョンを同期します。Chrome はプレリリース識別子を含むマニフェストのバージョンを拒否するため、2 つのファイルに同じ文字列を設定することはできません。そのため、数値のベース部分を version に、完全な文字列を version_name に設定します。
リリースを公開すると、ワークフローが実行されます。テスト、バージョンの整合性チェック、解決されたタグでの npm publish --provenance が行われ、拡張機能の ZIP ファイルがビルドされてリリースに添付されます。
チェックで推測は行わず、公開を拒否します。タグと package.json の不一致、更新されていないマニフェスト、またはプレリリースとしてマークされたリリースでの安定版バージョンがあると、実行は失敗します。最後のケースでは、そのバージョンが latest に公開され、誰もが利用するデフォルトのインストール版になってしまうためです。
公開せずに一連の手順を試すには、ワークフローの手動トリガーで dry_run: true を使用します。
テスト
npm install
npm test
フレームワークもブラウザーも必要ありません。2 つのテストスイートを実行します。
mcp-server/test/run.js— コンテンツスクリプトの注入の冪等性、シャドウ DOM の貫通、フレームをまたいだ検索、タブ移動時の読み込み競合、MCP サーバーの エンドツーエンドテストを実行します。ポート7931で偽の拡張機能を相手に実際のサーバープロセスを 起動するため、すでに実行中の PolterTab(ポート7822)に影響することはありません。test/setup.test.js— インストーラーのテストです。スコープの解決、スキルのインストール、CLAUDE.mdの冪等性を確認します。各ケースは使い捨ての一時ディレクトリで実行されるため、 書き込みが漏れて実際の~/.claudeに到達することはありません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。