Skip to main content
Glama

Daedalus

Chrome拡張機能によるリモートブラウザー制御。Evalブリッジ + 永続ホットフィックス + タブごとの制御 + スクリーンショット、CDP、クッキー、Chromeが拡張機能を実行しているページでのネットワークキャプチャ。

インストール

インストール前に知っておいてください: 通常のevalは、バナーなしのMAIN-worldインジェクションを使用します。ソースなしのCSPプローブが動的コンパイルの利用可能性を確認できない場合、DaedalusはCDPフォールバックを試みます。そのフォールバックの実行中にアタッチに成功すると、Chromeの「Daedalus started debugging this browser」バナーが表示されます。CDPセッションを維持したりネットワークキャプチャを続けたりすると、アタッチメントが長く保持される場合があります。バナーは、値の整合性の保証ではなく、デバッガーアタッチを示すものです。

Chromeで未パッケージの拡張機能(extension/)を読み込みます:

  1. chrome://extensions に移動

  2. デベロッパーモード を有効にする

  3. パッケージ化されていない拡張機能を読み込む をクリックし、extension/ を選択

初回インストール時に一意のトークンが自動生成され、chrome.storage.local に保存されます。拡張機能のオプションページ(パズルアイコン → Daedalus → Options)から表示・変更できます。

複数タブの並列スクレイピングを行うには、Chromeのバックグラウンドタブスロットリングを無効にしてください:

chrome --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-renderer-backgrounding

動作の仕組み

  1. Token: インストール時に crypto.randomUUID() で一度生成され、chrome.storage.local に保存される

  2. Tab IDs: Chromeの標準的な tabs API — 各タブはChromeの tabId で識別され、作成/更新時に30秒の chrome.alarms ハートビート付きで登録される

  3. 単一SSEストリーム: background.js が常駐の fetch SSE接続(tab=extension)を1本開き、受信コマンドを適切なタブに振り分ける

  4. Page bridge: content.js(ISOLATED world)は、バックグラウンドと page.js(MAIN world)の間で window.GM メッセージを中継する。Evalはまず chrome.scripting によるMAIN-worldインジェクションを使う。ソースなしCSPプローブがCSPでブロックされたページをCDPへルーティングし、そこへのアタッチに失敗した場合はページリレーにフォールバックする。どのチャネルでも、ページのMAIN-worldセマンティクスで実行される。

  5. Hotfixes: 拡張機能全体のストレージキー chrome.storage.localdaedalus-hotfixes(トークンごとではなく)に保存され、対象となるすべてのトップレベルページの読み込み時に再適用される。非永続修正はバージョンで制限される。トークンを回しても、このストアは分離もクリアもされない。

コマンドの送信

Daedalusは拡張機能のコマンド面を、<your-bridge>/mcp(streamable-HTTPトランスポート)でMCPサーバーとして公開します。リクエストを配送する前に、その処理はBearer値がCLIの既存設定パスを通じて解決されるブリッジトークンと完全に一致することを要求します。このパスにはオプションの _settings プロバイダを含みます。 TOKENDAEDALUS_TOKEN を上書きします。トークンが設定されていない場合、MCPのサーフェスはフォールトクローズし、401 を返します。Claude Code(または任意のMCPクライアント)に次のように追加します:

{
  "mcpServers": {
    "daedalus": {
      "url": "https://daedalus.example.com/mcp",
      "headers": { "Authorization": "Bearer <your-bridge-token>" }
    }
  }
}

ブリッジトークンは、拡張機能がインストール時に生成するものです。拡張機能のオプションページ(パズルアイコン → Daedalus → Options)で確認できます。

この例ではMCPサーバーをパブリックホスト名で公開していますが、トランスポートの既定の許可ホスト(ループバック)は 127.0.0.1:*,localhost:* のみです。DAEDALUS_MCP_ALLOWED_HOSTS でパブリックホスト名を指定しないと、プロキシされたリクエストは拒否されます。MCPの3つの設定すべては、後述の「Server」を参照してください。

7グループに40のツールがあります — tabs、eval/debug、media、cookies、CSS/blocking、hotfixes、network/CDP。完全なリストは CLAUDE.md<mcp> セクション、またはMCPエンドポイントの tools/list を呼び出してください。

手動検証ヘルパー(MCPクライアントは不要):

TOKEN=<tok> python3 scripts/mcp_probe.py list
TOKEN=<tok> python3 scripts/mcp_probe.py call title '{"tab_id":"<tabId>"}'
TOKEN=<tok> python3 scripts/mcp_probe.py call screenshot '{"include_image":true}'

CLI

このリポジトリにはシェルベースのCLIが daedalus_cli/ ディレクトリの daedalus-cli wheel として同梱され、daedalus コマンドとしてインストールされます。環境変数 DAEDALUS_URLDAEDALUS_TOKEN を読み取り、TOKEN は一回限りの上書き、ID=<tabId> はタブごとのターゲットに使用します(省略するとブロードキャスト)。

DAEDALUS_TOKEN=<tok> daedalus tabs
DAEDALUS_TOKEN=<tok> ID=<tabId> daedalus title
DAEDALUS_TOKEN=<tok> daedalus exec myid 'document.title'

daedalus --help ですべてのサブコマンドを一覧表示でき、各サブコマンドにも --help があります。送信する exec コードは、戻り値が結果として返される式または関数本体です。契約の詳細については上記「Sending Commands」を参照してください。

任意のインポートシームも利用できます:sys.path_settings というモジュールがインポート可能な場合、CLIは組み込みの環境変数フォールバックの代わりに、setting(name, default)required(name) の関数を使って DAEDALUS_URLDAEDALUS_TOKEN を取得します。環境変数 TOKEN は一回限りのトークン上書きとして残り、優先されます。 _settings がない場合、DAEDALUS_URL はその既定値を使い、DAEDALUS_TOKEN は必須です。 ID は引き続きタブごとのターゲットを指定する環境変数です。

または、生のコマンドファイルをアトミックに公開することもできます(MCPもCLIも不要)。最終的な .json 名への直接リダイレクトは、書き込みプロセスが完了する前にストリームがファイルを観測する可能性があるため、サポートされていません。まず同一ディレクトリ内に .tmp で終わる名前を書き、その後にリネームしてください:

# Broadcast to all tabs
commands_dir="$DAEDALUS_DIR/commands"
final="$commands_dir/<token>.json"
tmp="$(mktemp "$commands_dir/.<token>.XXXXXX.tmp")"
printf '%s\n' '{"id":"test1","code":"document.title"}' > "$tmp" &&
  mv "$tmp" "$final"

# Target a specific tab
final="$commands_dir/<token>_<tabId>.json"
tmp="$(mktemp "$commands_dir/.<token>_<tabId>.XXXXXX.tmp")"
printf '%s\n' '{"id":"test1","code":"document.title"}' > "$tmp" &&
  mv "$tmp" "$final"

リーダーは、同じディレクトリの .tmp の兄弟ファイルを無視します。書き込み者が古い無効なJSONを最終名で公開した場合、リーダーはそれをそのままにして、書き込み途中である可能性があるファイルを削除せずに再試行します。アトミックリネーム後、SSEストリームがコマンドを配信して消費します。結果は $DAEDALUS_DIR/results/<token>_<tabId>.json(タブごと)と $DAEDALUS_DIR/results/<token>.json(最後の書き込み者優先)が得られます。page-main インジェクションとページリレーのeval完了には、ページコンテキストの実行時間(ミリ秒)である exec_ms フィールドが含まれることがあります。ページは、どちらのチャンネルでもこのページ計測フィールドを改ざんまたは省略できます。CDPの完了には exec_ms はありません。また、受信キューに関連付けられた結果には roundtrip_ms も含まれます。これはコマンドの受付(PUT /command)から結果到着(POST /result)までのサーバー観測の往復時間(ミリ秒)です。キュー待ち、SSE配信、クライアントリレー、実行、復路を含むため、roundtrip_ms - exec_ms は両方のフィールドがある場合、トランスポート/キューのオーバーヘッドを約それを反映します。ただし、これらの計測は異なるクロックに依存します。 exec_ms はページの performance.now() を、roundtrip_ms はサーバーの壁時計ミリ秒を使うため、それらの差は正確な減算ではなく近似値です。_did を持たないレガシーフレームには roundtrip_ms がありません。

非同期サポート

既定の page-main チャネルは、式をページ所有 eval、関数本体をページ所有の Function で実行します。非同期ラッパーがトップレベル await を提供します。ソースを送信する前に、バックグラウンドは定数 Function プローブだけをを送信します。そのプローブが true を返した場合、ソースの注入は1回だけ試行され、その後どんな結果(値、例外、注入トランスポートエラー)でも終端として報告されます。 CDPでソースを再試行することはありません。ページは Function を所有しルーティングのヒントに影響を与えることができますが、このプローブは送信済みのソースに含まれないため、別のチャネルを選択しても、その副作用を重複させません。

ソースフリープローブが true を返さない場合は、ページCSPが動的コンパイルをブロックすることが多いため、CD Pを試します。アタッチ成功: CDP成功すると Chromeのデバッガーバナーが表示されます。Runtime.evaluate は、トップレベルの、実行待機のREPLモードを使います。ラッパープローブが式として解析しない限り、return を含むソースは関数本体として扱われます。そのラッパープローブはパースのヒューリスティックであり、実行可能なセキュリティ境界ではありません。細工したソースはそれを回避して実行できます。最終的なCDP評価をディスパッチした後は、どの結果も終端です。送信したソースが実行される前にアタッチまたは形状の失敗が発生した場合のみ、ページリレーにフォールバックします。CDPのプロミス確定は10秒に制限され、セッション維持やキャプチャーがデバッガーのアタッチを保持しても、そのク結果と例外のオブジェクトハンドルは解放されます。

制御していないページで評価されたJavaScriptは、どのチャネルで実行されたかに関係なく、そのページが選んだそこの値を返します。 world フィールドは、送信されたソースがどの実行チャンネルで実行されたかを記録するだけです。CSPとデバッガーの動作を診断するためのメタデータであり、信頼のシグナルではありません。その評価値は、通常のインジェクションでは page-main、インスペクターフォールバックでは cdp、最終リレーでは page:<hostname><hostname> はコンテンツスクリプトの location.hostname)です。バックグラウンドは page: プレフィックスを付けるため、リレーのホスト名が cdppage-main と衝突することはありません。この名前空間の事実は返される値についてべ約束しません。 CLIとダッシュボードは、このフィールドを channel=... として表示し、MCP の execputresultpingworld の値をそのまま保ちます。どれも信頼クラスを割り当てません。

既定のインジェクションとCDPフォールバックは、文書化されたスロッピーモードの場合に対しても、クラシックスクリプトの振る舞いを維持します。 with はコンパイルされ、古い8進数リテラルは受け入れられ、宣言されていない代入はグローバルを作成します。CDPのREPLモードでは、 let または const の再宣言も許可されます。CLIとMCPは結果待ちが既定で15秒ですが、呼び出し元がタイムアウトしてもページ内で動いているコードがキャンセれることはありません。Blob relay は await を含むコードでは最大10秒、それ以外では最大3秒待つリフォールバックタイムを報告します。

リレーの相関方向は記述的で境界ます: 送信元タブが一致する必要があり、1つの受理されたメッセージがランダムな relay id を使入し、ソースなしinjectionプロトローブとディスパッチ前のCDPフォールバックが完了するまで relay id は登録されません。これらの制御は、タブ間またはタブ間リレー終了を防ぎますが、値の完全性—は確立しません。

ページリレーの同時エントリは最大1,000件です。データが新しいフォールバックで持つ場合、実行中の作業を追い出さず終端状態の容量タイムで error を1回受け取ります。登録された各エントリは300,000msで期限切れになり、同一タブの完了またはそれ以前の送信失敗で削除されない場合、終端のタイムアウトエラーを1回受けます。

ダッシュボード

<your-bridge>/dashboard のブラウザベースのは、CLIなしで拡張機能のコマンドセット全体を操作できます。ライブタブリスト、eval REPL、スクリーンショット、クッキー、ホットフィックス、ブロックルール、ネットワークキャプチャ、CDP、CSSインジェクション、fetchタイミング、アップロードブラウザなど。

  1. 拡張機能が制御しているタブでURLを開く。

  2. §12 Settings までスクロールし、拡張機能のオプションページ(パズルアイコン → Daedalus → Options)からトークンを貼り付けて保存する。

  3. ダッシュボードがライブイベントを購読すると、トップバーのSSEステータスのドットがシアンになります。

server.py はリポジトリの dashboard/ ディレクトリから直接配信(バニラJS + ESモジュール、ビルドなし)。ライブの更新は既存の /stream エンドポイントを通じて行われます: server.py は、/register が既存のタブを更新する場合と、/sync-tabs, /unregister, /result の成功パスに加え、/unregister がタブなしでもイベントを commands/<token>_dashboard/<ts>_<uuid>.json に追加します。ダッシュボードはそれらを kind:'event' のフレームとして消費します。

注意: 拡張機能のContent / Pageスクリプトは、ダッシュボードのタブを含むすべての一致ページに注入されます。ブロードキャストeval(exec -b)もダッシュボード内で実行されるため、タブごとのターゲットを指定締切するか、破壊的なコードをブロードキャストする前にダッシュボードを閉じてください。

セルフパッチ

ホットフィックス

該当するトップレベルページの読み込みごとに再生される小さなパッチを永続化します。MCPツール: store_hotfix, list_hotfixes, clear_hotfix, clear_hotfixes, set_permanent(例:プローブスクリプト経由)

TOKEN=<tok> python3 scripts/mcp_probe.py call store_hotfix '{"fix_id":"my-fix","code":"console.log(\"patched\")"}'
TOKEN=<tok> python3 scripts/mcp_probe.py call store_hotfix '{"fix_id":"always-on","code":"console.log(\"baseline\")","permanent":true}'
TOKEN=<tok> python3 scripts/mcp_probe.py call set_permanent '{"fix_id":"my-fix","permanent":true}'
TOKEN=<tok> python3 scripts/mcp_probe.py call list_hotfixes
TOKEN=<tok> python3 scripts/mcp_probe.py call clear_hotfix '{"fix_id":"my-fix"}'
TOKEN=<tok> python3 scripts/mcp_probe.py call clear_hotfixes
TOKEN=<tok> python3 scripts/mcp_probe.py call clear_hotfixes '{"include_permanent":true}'

ホットフィックスは既定でバージョンゲートされます。拡張のバージョンが変わった場合は、保持された非永続フィックスは削除されずにスキップされます。フィックスを保存するとレコードが現在のバージョンに更新され、引き続き残っている非永久フィックスが再び対象になります。フィックスを permanent にする(注意: store_hotfix) で permanent: true、または set_permanent で、バージョン変更後も再生を継続します。clear_hotfixes は既定で非永続フィックスを削除し、永続フィックスは残します。include_permanent: true を渡すとストア全体を削除します。

拡張コマンド

バックグラウンドサービスワーカーは、型付きコマンドを受け付けます(MCPツールを経由するか、"type": "..." を持つJSONを $DAEDALUS_DIR/commands/ に書く):

コマンド

目的

screenshot

表示中のタブを PNG としてキャプチャする

cdp

生の Chrome DevTools Protocol 呼び出しを発行する

net-capture / net-capture-stop / net-capture-get

CDP による完全なリクエスト/レスポンスの傍受

cookies / set-cookie / remove-cookie / clear-cookies

Cookie ジャーへのアクセス

open-tab / open-tabs / focus-tab / close-tab / navigate / reload

タブ制御

inject-css / remove-css

タブごとの CSS 注入

block-requests / unblock-requests / list-block-rules

declarativeNetRequest によるブロック

store-hotfix / clear-hotfix / clear-all-hotfixes / list-hotfixes / set-permanent

ホットフィックス管理(永続フィックスはバージョンアップ後も保持されます)

ext-reload

拡張機能自体をディスクからリロードする

fetch-timings

fetch リレー用の診断リングバッファ

GM ブリッジ

window.GMpage.js 内、MAIN ワールド)は、次の Tampermonkey スタイルのサブセットを提供します:

メソッド

説明

GM.getValue(key, default)

拡張全体の chrome.storage.local から予約されていない文字列キーを読み取る(トークンごとではない)

GM.setValue(key, value)

拡張全体のストレージに予約されていない文字列キーを書き込む

GM.deleteValue(key)

拡張全体のストレージから予約されていない文字列キーを削除する

GM.listValues()

予約されていないストレージキーを一覧表示する

GM.xmlhttpRequest(opts)

バックグラウンドで中継される HTTP リクエスト(CSP の影響を受けない)

GM.addStyle(css)

CSS を注入する

GM.setClipboard(text, type)

クリップボードに書き込む

GM.notification(opts)

デスクトップ通知

GM.openInTab(url, opts)

新しいタブを開く

GM.download(opts)

ダウンロードを開始する

GM.info

スクリプトのメタデータ

Cookie へのアクセスは、ページの能力ではなくオペレーターの能力です。これは、上記のトークン認証された cookies / set-cookie / remove-cookie / clear-cookies コマンド経由でのみ行われ、ページのコンテキストには意図的に公開されません。page.js は一致するすべてのトップレベルページで実行されるため、公開されていたら、ページは自身の document.cookie には見えない Cookie を読み取れてしまうからです。

アーキテクチャ

Browser (matching tab)                           Server (your bridge host)
┌────────────────────────────────────────────┐   ┌──────────────────────┐
│ MAIN world                                 │   │ bridge (server.py)   │
│  ├─ page-main: default injection channel   │   │ /stream?token        │
│  └─ page.js: GM + relay channel            │   │ watches commands/    │
│            ▲                               │   │                      │
│            │ window.postMessage            │   │ /result writes       │
│ content.js (ISOLATED)                      │   │    results/          │
│            ▲                               │   │                      │
│            │ chrome.runtime                │   │                      │
│ background.js (service worker)             │   │                      │
│  ├─ CDP: CSP fallback channel              │   │                      │
│  ├─ single SSE stream ◄────────────────────┼───┤                      │
│  └─ POST result, fetch ────────────────────┼──►│                      │
└────────────────────────────────────────────┘   └──────────────────────┘
  • 単一の SSE ストリーム: バックグラウンドが 1 つの fetch SSE 接続(tab=extension)を開き、chrome.tabs.sendMessage 経由でコマンドを対象のタブに転送します。30 秒のウォッチドッグが、停止したストリームに対する再接続を強制します。

  • タブごとのルーティング: コマンドは特定の Chrome tabId を指定するか、またはすべてのタブにブロードキャストします。

  • CSP の挙動: GM.xmlhttpRequest は HTTP 処理をバックグラウンド service worker の fetch に送ります。eval は通常、バナーなし MAIN ワールド注入を使用します。ソースフリープローブが動的コンパイルを利用できないと報告した場合、CDP が CSP フォールバックを提供し、待ち受けると Chrome のデバッガバナーを表示します。アタッチに失敗した場合は、ページ/Blob リレーにフォールバックします。結果として得られる world 値はその経路を説明するものであり、完全性を保証しません。

サーバー

ブリッジは必須の 3 つの設定で起動してください。DAEDALUS_DIR または DAEDALUS_PORT がないと起動時に終了し、ブリッジ制御のルートはすべて設定済みトークンがないとフェイルクローズします:

DAEDALUS_DIR=<data-dir> DAEDALUS_PORT=<port> DAEDALUS_TOKEN=<bridge-token> python3 server.py

server.py は、あなたが使っているスーパーバイザーの下で実行されます(ここでは systemd ユニット)。localhost を超えて公開する場合は、TLS 終端のリバースプロキシを前に置いてください。ブリッジ自体は平文 HTTP を話します。ブリッジ制御ルートとストレージルートは、設定済みのシークレットとトークンを比較し、そのシークレットは CLI の設定パスで解決されます。TOKEN がその場限りのオーバーライドであり、そうでなければ DAEDALUS_TOKEN が必要です(埋め込まれた _settings モジュールがそれを提供する場合もあります)。設定がない場合や不一致の場合はフェイルクローズです。ページ向けの POST /segmentGET /segment-status ルートのみ、代わりにジョブスコープのケイパビリティを使用します。

プロセス内 MCP フロントエンドは 3 つのオプション設定を受け取ります。それらは一つのリスナーを記述するものなので一緒に説明します。DAEDALUS_MCP_PORT(既定 8086)はバインドするループバック ポートです。ツールハンドラーは、DAEDALUS_PORT=0 の場合も含め、ブリッジが実際にバインドしているループバック URL を使用します。DAEDALUS_LOCAL_URL は、別の場所で実行しているブリッジを前面で立てるスタンドアロン MCP デプロイ用の URL を明示的に上書きします。また、DAEDALUS_MCP_ALLOWED_HOSTS(既定 127.0.0.1:*,localhost:*)は、DNS リバインディング保護が受け入れるホストの許可リストで、/mcp を公開ホスト名で受ける場合は、そのホスト名をここに記載します。

エンドポイント: GET /stream, GET /tabs, GET /health, GET /dashboard[/<asset>], POST /register, POST /sync-tabs, POST /unregister, POST /poll, POST /result, PUT /command, GET /result, POST/GET/DELETE /upload, GET /screenshot, POST /segment-job, POST /segment + GET /segment-statusPOST /segment-job には設定済みのブリッジトークンが必要です。ジョブスコープの sig を受け取るのは POST /segmentGET /segment-status のみです。ペイロードとエンドポイントについては CLAUDE.md を参照してください。

POST /poll は、レガシーブロードキャストコマンドファイルが存在する場合に、それを消費して削除します。

PUT /command は、ターゲットごとの FIFO ディレクトリキューにエンキューします(同じタブへの連続したコマンドが上書きされなくなりました)。各コマンドには配信 ID (_did) が付与され、拡張機能が再配信されたフレームを重複排除できるようになります。さらに、DAEDALUS_CMD_TTL 秒(既定 90)以内に受け取られなかったコマンドは TTL で破棄されます。バックグラウンドのコレクターがその TTL を適用し、SSE コンシューマーが一度も接続しない場合でも、空のキューディレクトリを削除します。GET /health は、ストリーム/レジストリ/最終配信の生存状況を取り込んで、静かに死んだブリッジを検出できるようにします。

ブリッジは、権限を示す "繰り返し" がある場合、どれかを選択するのではなく拒否します。対象は、クエリ文字列や JSON ボディ内の token、セグメントのケーパビリティを持つルートの job / sig で、その場合も、繰り返された値が同一または空であっても拒否されます。MCP トランスポートも同様に、反復する AuthorizationMcp-Session-IdHostOrigin ヘッダー、またセグメントツールへの反復する job 引数を拒否します。

拡張機能が結果を POST すると、サーバーはコマンドの _diddeliveryId として公開し、新しい resultGeneration を割り当てます。CLI と MCP の待機者は、まず共有された結果スロットを覗いて、コマンド ID と deliveryId の両方を照合し、その世代を GET /result?...&consume=1&expected=<resultGeneration> で条件付きで消費します。別の結果がリクエストの間にスロットを置き換えた場合、条件付きの消費は新しい結果を残したまま、その結果は消費されなかったことを報告します。expected のない裸の consume=1 は、現在のスロットに対する破壊的な互換読み取りとして残ります。

GET /stream は SSE 接続を無期限に開いたまま保持し、DAEDALUS_STREAM_KEEPALIVE秒(デフォルト 15 秒)ごとに keepalive コメントで生存を示し、タイマーで接続を張り替えることはありません。DAEDALUS_STREAM_MAX_AGE(デフォルト 3600 秒)は、あくまで最後の手段の上限です。クローズパスは tests/test_stream_lifecycle.py によって固定されています。

DAEDALUS_MAX_BODY_SIZE(デフォルト 64 * 1024 * 1024 バイト、64 MiB)は、POSTPUTDELETE ハンドラーが読み取る大きなリクエストボディを制限し、最大値を超えるとリクエストは 413 を受け取ります。より大きなセグメントやその他のペイロードを中継する場合は、これを増やしてください。

Files handler で使用する "caller value" には、1 パスコンポーネントポリシーを適用します。..、C0/C1 制御文字とサロゲート文字、Windows で無効なパス文字とデバイス名、末尾のドットやスペース、240 バイトを超える UTF-8 エンコーディングを拒否します。ブリッジトークンはさらに厳しく、ドットとアンダースコアも拒否します。他の UTF-8 ジョブは受け付けられるため、クライアントはクエリ文字列で URL エンコードする必要があります。

POST /segment-job は、新しい各ジョブレコードに 3 つの固定クォータをコピーします: DAEDALUS_MAX_SEGMENT_INDEX(デフォルト 99999)、DAEDALUS_MAX_SEGMENTS_PER_JOB(デフォルト 10000)、および DAEDALUS_MAX_SEGMENT_JOB_SIZE(デフォルト 4 * 1024 * 1024 * 1024 バイト、または 4 GiB)。これらの設定変更は後に作成されるジョブにのみ反映されます。設定が保存されている既存のジョブは、記録済みの値を使い続けます。個々のセグメントリクエストもで、パラレルに DAEDALUS_MAX_BODY_SIZE の制限を受けます。

セキュリティ

拡張機能をインストールする前に、この内容を読んでください。

これは window.GM のシムを、一致するすべてのトップレベルページ<all_urls>、MAIN ワールド)に注入します。これが、put で送信したスクリプトにクロスオリジンリクエストを可能にしています。その結果を意図的に認識してください: アクセスする一致するサイトは、その シムを呼び出し、できるため、そのサイトは拡張機能の特権を介してクロスオリジンリクエストを実行できます。ワイルドカード @match のユーザースクリプトマネージャーとまったく同じです。あなたがブラウジングで受け入れられない場合は、extension/manifest.jsonmatches をあなたが実際に操作するホストに限定し、ブリッジが他のページでは何もしないことを受け入れてください。

ブリッジトークンとサーバー URL のGM storage**の方法ではアクセスできません。domainは chrome.storage.localdaedalus- プレフィックスに保存され、リレーはページスクリプトのためにその名前空間を読み取り、書き込み、列挙することを拒否します。このルールがないと、訪問した任意のサイトが GM.getValue('daedalus-token') でブリッジトークンを読み取ったり、GM.setValue('daedalus-server', ...) でブリッジを静かに偽装できたりします。tests/test_repo_contract.py がこのルールを固定します。

ホットフィックスのソースは、意図的にページ配信される状態であり、秘密の拡張状態ではありません。content.jsdaedalus-hotfixes レコードを読み取り、永続フィックスに拡張バージョン対応固定のフィックスを選択し、選択した完全オブジェクトを各適格ページへ送ります。メインワールドの page.js は各オブジェクトの code を存在するため、ページはページ配信のそのソースを検証できます。

MCP ベアラーは、MCPプロセスに読み取らせたければ、サーバーホストのファイル名を指定できません。 MCP の put、CSS 注入/除去、ホットフィックス保存ツールは、インラインソースのみにはいます。ローカルコマンドラインは、ファイルパスにま特別に、そのオペレーターが選択したファイルを、コマンドラインのプロセスが読み込んで、その内容を inline で送信します。したがって、ブリッジトークンを持つことは、保存済みのホットフィックスソースを読み取ることも含め、文書化されたブラウザと拡張機能の制御権限を付与しますが、それらのツールを介しても任意のホストファイルシステムを読み取れるようにしたわけではありません。

ブリッジ制御ルートとストレージルートは、設定されたブリッジトークンを必要とし、/segment/segment-status だけがキャパビリティ例外です。 サーバーは、リクエストのトークンを TOKEN または DAEDALUS_TOKEN から解決したシークレットと比較し、シークレットが設定されていない場合はリクエストを拒否します。POST /segment-job はジョブスコープのキャパビリティを発行するため、そのブリッジトークンが必要です。信頼できないページの JavaScript は、そのキャパビリティで当該ジョブの投稿と問い合わせしかできません。ブリッジトークンを保持する者は誰でもあなたのブラウザを操作できます。TLS を終端するリバースプロキシなしにブリッジポートをループバックの外に公開しないでください。トークンは資格情報として扱ってください。

Eval 結果は値の整合性を保証するものではありません。 あなたが制御しないページで評価された JavaScript は、どの経路で実行されたかにかかわらず、そのページが自由に決められる値を返します。world フィールドは、送信されたソースがどのように実行されたかを示すだけで、その値を信頼すべきかどうかを示すものではありません。page-main は通常の MAIN-world 注入、cdp はインスペクタの CSP フォールバック、page:<ホスト名> はリレーです。必須の page: プレフィックスはページコンテキストの外で追加されるため、どのホスト名も cdppage-main を作り出せません。この衝突耐性はあくまで記述的なものです。page-main 上では、ページが所有する evalFunction バインディングは、送信ソースを読み取るだけでなく、返される値を操作することもできます。

CDP コンパイルはページの evalFunction バインディングの解決を回避し、実装はシリアライズ前に直接ハンドルを参照で取得します。それらのトランスポート実装は信頼境界を変えません。送信されたソースは依然としてページ管理の状態を読み取ることができ、CDP が受け取る前に、プリミティブを含むあらゆる値をページのプロミス機構に通すことができます。送信されたソースがそれらのページ管理の経路を使うとき、ページは cdp 上で返る値も選べます。

リレーは、そのランダム id に関連付けられた保存済みの呼び出しだけを受け付け、送信元のタブが一致することを要求し、エントリを一度だけ消費します。このダウングレードは、ブリッジトークン、サーバーURL、配送 ID、結果ルートを開示しません。追加の拡張機能権限やブラウザ権限を付与せず、別のタブでの呼び出しに影響を与えません。これらの特性はルーティングとブラウザ権限を保護するものであり、リレーのマーカーやそれが返す JavaScript の値を信頼シグナルに変えるものではありません。

Deployment

ブリッジはループバック上で平文 HTTP を話します。ブリッジ制御ルートとストレージルートは、設定されたトークンを要求し、トークンがない場合はフェイルクローズします。キャパビリティを使うのは /segment/segment-status だけです。ブリッジが意図的に行わない 2 つのことは、それらの責務がその前に置かれる何かのものだからです。

  • TLS と CORS。 server.py は CORS ヘッダーを一切送信しません。ブリッジがクロスオリジンにある場合、例の HLS リレーのページ側 fetch 呼び出しは GET /segment-statusPOST /segment の両方にアクセスできる必要があります。プロキシは両方のルートでページのオリジンを許し、POST のプレフライトが必要なメソッドとヘッダーを扱わなければなりません。ステータス取得 GET がブロックされたり、利用不可、非 2xx、または無効な場合、例はジョブを新しいものとして扱い、すべてのセグメントを再 POST します。その書き込みは同じインデックスのファイルに置き換わるだけですが、実行の再開・スキップの節約が失われます。ページは、展開先がその CORS ポリシーを提供できない場合は、代わりに拡張機能の GM ブリッジ経由で両方のリクエストをルーティングします。

  • **保存済みアップロードの配信。**だashboard は /uploads/<path> でダウンロードにリンクしますが、ブリッジにはそのようなルートはありません。実行可能コンテンツがデッシュボードのトークンを含むストレージとオリジンを共有するため、呼び出し元指定のアップロード名とバイト列をダッシュボードのオリジンに直接配信しては、許可されません。それらのリンクを利用できないままにするか、/uploads/ を別のダウンロード専用オリジンへのリダイレクトして、Content-Disposition: attachment を強制し、application/octet-stream を使用し、X-Content-Type-Options: nosniff を送るようにします。GET /upload(一覧)と GET /screenshot はブリッジ自身が処理するため、プロキシの助けは不要です。

設定したトークンで直接実行すると、これら 2つはただ存在しないだけです。他はすべて機能します。

Files

File

Description

extension/manifest.json

MV3 マニフェスト

extension/background.js

Service worker — SSE、コマンドディスパッチ、fetch リレー、スクリーンショット、CDP、Cookie、ダウンロード

extension/content.js

ページとバックグラウンド間のメッセージリレー

extension/page.js

MAIN-world ブリッジ — window.GM + eval ハンドラー

extension/options.html / options.js

トークン/サーバー設定 UI

server.py

デバッグサーバー(127.0.0.1:8086 で MCP デーモンスレッドもホスト)

mcp_server.py

MCP サーバー — 拡張機能のコマンド表面を HTTP 経由で server.py にブリッジ

scripts/mcp_probe.py

手動確認用の最小限の MCP クライアントヘルパー

scripts/check_versions.py

全バージョン箇所で整合性のバージョンをチェック/バンプする

.githooks/

pre-commit + pre-push のバージョン整合性ゲート

daedalus_cli/

シェル CLI で、daedalus-cli wheel として公開

dashboard/

server.py/dashboard で提供するブラウザ操作画面

examples/

ページ内で put を使って実行するスクリプト — 下記参照

tests/run_tests.py

テストスイート群; python3 run_tests.py がすべて実行する

Examples

examples/ には、ページ内で put を使って実行する想定のスクリプトが入っています。6 つのうち 5 つは機能を説明しており、特定のサイトではなくブリッジの一部を示しています。Discord 用のは意図的にサイト固有です。仮想化されたリストを遡って挿げ替える方法は、実際に仮想化されたリストなしには示せないからです。

Example

Shows

request-log-hotfix.js

document_start での恒久的な MAIN-world ホットフィックス、および、その重要な意味を持つ 語それぞれ

hls-segment-relay.js

/segment + /segment-status リレー: 再開可能、冪等、再試行回数制限付き

kill-hls.js

再試行を止めないプレイヤーインスタンスを見つけて破壊する方法

react-fill-input.js

React 制御された入力欄を、実際に React 自身の state が変わるように埋める方法

scrape-discord-messages.js

仮想化されたメッセージリストを遡ってスクロールし抽出する方法

open-tabs.js

可能な限り最小の GM.openInTab 呼び出し

これらは、送信前に __PLACEHOLDER__ 置換によって設定を受け取ります。put は関数を呼び出すスクリプトではなく、引数を渡す方法がないためです。

それぞれはスタンドアロンのスクリプトではなく、非同期関数の本体です。ブリッジがあなたの送信内容をラップするからです。だから、ほとんどは最上位の return で終わり、そのうちの 1 つ — scrape-discord-messages.js — は最上位の await も使います。どちらも、実際に実行される場所では有効です。node --check は各ファイルを CommonJS ラッパーとして解析します。これにより、最上位の return は許可されますが、最上位の await は拒否されます。そのため、まさにそのファイルだけが構文チェックに失敗するのです。

Development

バージョン文字列は、拡張機能、ダッシュボード、CLI パッケージの複数の場所に存在します。python3 scripts/check_versions.py がその一覧です。各場所を列挙して発見数を報告するため、この段落には数値を書いたりしません。それは、次に追加したときに古くなるからです。必ずまとめてバンプ、手作業ではやらないでください:

python3 scripts/check_versions.py --set 0.18.0   # rewrite every site
python3 scripts/check_versions.py                # verify the working tree

.githooks/pre-commit はインデックスをチェックし、.githooks/pre-push はプッシュされた各コミットをチェックするため、中途半端なバンプが入ることはありません。すべてのクローンは一度だけオプトインする必要があります — そうしないと、git がトラッキングしたディレクトリ内のフックを実行しないからです。

git config core.hooksPath .githooks
-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.

  • Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.

  • Access Kernel's cloud-based browsers and app actions via MCP (remote HTTP + OAuth).

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nitjsefnie-Harness-Commons/daedalus'

If you have feedback or need assistance with the MCP directory API, please join our Discord server