Skip to main content
Glama
thekk1

playwright-mcp-guarded

by thekk1

playwright-mcp-guarded

Microsoft の playwright-mcp を、ドメイン制限付きでユーザーに紐付かない形で包むラッパーです。LibreChat アシスタント向けの汎用 Web 取得・閲覧の代替手段(GitHub、Wikipedia、Google、Google Scholar、...)であり、ドメインの許可リストに限定され、環境変数を1つ編集するだけで拡張できます。プレーンな streamable-HTTP の Docker サービス(ports: は公開せず、ユーザーごとの OAuth もなし)として、同じ構成に従う姉妹プロジェクト time-mcp-http および ews-mcp のマルチユーザーモードと並んでデプロイされます。

なぜ素の @playwright/mcp を直接実行しないのか

この目的にぴったりの --allowed-origins/--blocked-origins がすでにあり、このプロジェクトはその強制を再実装しません。実際に許可されていないナビゲーションをブロックするのは、依然としてこの機能です。素のまま実行した場合に欠けている点が2つあります:

  1. 公式ドキュメントでは --allowed-origins は「セキュリティ境界ではない」とされています。既知のギャップとして、Service Worker と WebSocket のトラフィックは、この機能の基盤である context.route() によるインターセプトを迂回します。--block-service-workers(ここでも無条件に設定済み)はそのギャップの1つを塞ぎますが、もう1つに対応するフラグはありません。

  2. 許可リストは、呼び出し側モデルが参照できるどこにも表示されません。initialize の instructions にも、どのツールの description にも含まれません。モデルはどのドメインに到達可能かを事前に知る手段がないため、ブロックされたドメインごとに毎回、試行して初めて分かります。

Related MCP server: Airlock

仕組み

コンテナ1つ、プロセスツリー1つ、設定値1つ(ALLOWED_ORIGINS):

LibreChat --(streamable-http, /mcp)--> guardian (Python, PID 1)
                                          |
                                          | spawns as child process,
                                          | on loopback only
                                          v
                                    @playwright/mcp (Node, --allowed-origins)

guardian/app.py は、変更を加えていない本物の @playwright/mcp CLI を、localhost のみにバインドした子プロセスとして起動し、MCP クライアントとして接続した上で、コンテナの公開ポート上で MCP サーバーとして再公開します。tools/list と initialize には可視化のためドメインリストが追記され、tools/call はそのまま転送されます。独自のツールロジックはなく、この2つのテキスト編集以外に動作の変更はありません。ALLOWED_ORIGINS は起動時に一度だけ読み込まれ、両方に渡されます。すなわち、起動されたプロセス(--allowed-origins として。これが実際の強制です)と、2つのレスポンス書き換え(可視化のみ)です。後からリストを拡張するには、この単一の環境変数を1行変更するだけです。同期を取る必要のある2つの設定に分かれることはありません。

実行

docker build -t playwright-mcp-guarded .
docker run --rm -p 8080:8080 \
  -e ALLOWED_ORIGINS="github.com;raw.githubusercontent.com;wikipedia.org;en.wikipedia.org;google.com;scholar.google.com" \
  playwright-mcp-guarded

ALLOWED_ORIGINS はセミコロン区切りです。@playwright/mcp 自体が PLAYWRIGHT_MCP_ALLOWED_ORIGINS に使用している形式と同じです。空の値はすべてのドメインをブロックします(起動時に警告としてログに記録され、黙ってバイパスされることはありません)。

EXTRA_INSTRUCTIONS(任意・自由記述)は、モデルが見る initialize の instructions にそのまま追記されます。許可リストは、どのドメインに到達できるかだけを示し、その先にあるものをどのように使うかは示しません。たとえば、セルフホスト型検索エンジンのクエリ構文などです。ここでハードコードしないのは意図的な選択です。このラッパーはドメインに依存しないまま保たれ、デプロイ担当者が、それぞれの許可リストが必要とする運用知識を自分の言葉で提供します:

-e EXTRA_INSTRUCTIONS="Search: http://searxng:8080/search?q=<term> (general), add &categories=science for Google Scholar results."

MCP_API_KEY はなく、MCP 接続自体にも認証ゲートはありません。意図的であり、ews-mcp/time-mcp-http と同じ理由です。いずれかのゲートから 401 が返ると、LibreChat の OAuth 非対応 MCP クライアントが OAuth を試行して(そこで詰まってしまい)ます。境界となるのは Docker のネットワーク分離です。このサーバーを通過する資格情報は一切なく、公開ページを読むだけです。

意図して受け入れたトレードオフであり、見落としではありません: 強制は Playwright のアプリケーションレイヤー(現在は --block-service-workers 付き)に置かれており、独立したネットワークレベルの境界(たとえば egress プロキシ)ではありません。これは意図的なシンプルさの選択であり、デプロイ可能なユニットが1つ、設定値が1つということであって、これが完全に隙がないという主張ではありません。ネットワークレベルのバックストップは、このロジックに一切触れることなく、後から重ねることができます。

検証

curl -s http://127.0.0.1:8080/readyz   # "ok" once the upstream browser is up

ログには、アップストリーム自身の起動行(Listening on http://localhost:<internal-port>)に続いて playwright-mcp-guarded up, allowed origins=... が表示されるはずです。この2行目は、設定された内容をそのまま写したものではなく、現在実際に強制されているリストです。

テスト

pip install -e '.[dev]'
ALLOWED_ORIGINS="github.com;wikipedia.org" pytest

ユニットテストのみです(description/instructions の書き換え、引数のパススルー)。Chromium や Docker を起動しません。Docker イメージは手動によるエンドツーエンド検証済みです。ビルドして実行し、実際の MCP クライアントが接続してツールを一覧表示し(許可リストは initialize.instructions と browser_navigate の description の両方に表示される)、許可されたドメイン(en.wikipedia.org)へのナビゲーションに成功し、許可されていないドメイン(example.com)では net::ERR_BLOCKED_BY_CLIENT が返りました。強制と可視性の両方が、主張だけでなく実機で確認されています。

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to search the web, fetch news, and retrieve page content via DuckDuckGo or Brave Search, with domain whitelisting and audit logging.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables LLM agents to safely search and fetch content from a single configured domain, preventing data exfiltration through deterministic enforcement.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to automate browsers through Playwright behind multi-layer safety guards, restricting navigation to allowed domains, defaulting to read-only actions, and recording all behavior in audit logs.
    7
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to fetch and process web content securely, including HTML-to-markdown conversion, reader mode, metadata extraction, RSS/sitemap parsing, and robots.txt-aware requests with SSRF protection.
    15
    805 npm
    2
    MIT