mcpField
L
lan-direct

lan-direct

ローカル
github.com/farshadmomoブラウザ自動化412 週間前に更新

lan-direct について

lan-directは、フルトンネルVPNを使うコーディングエージェント向けに、ブラウザーMCPサーバーとスキルを提供します。プロキシはホスト名ごとに経路を分け、指定ホストはISP経由、それ以外のブラウザー通信とエージェントはVPNトンネルに残します。

主な機能

  1. 01ホスト名ごとのブラウザー接続ルーティング
  2. 02指定ホストをISP経由で接続
  3. 03未登録の通信をVPNトンネルに維持
  4. 04Playwright MCPサーバーとエージェントスキルの提供
  5. 05ホストルールの追加と確認

活用シーン

  1. 01VPNのIPを拒否するサービスを呼び出すアプリのテスト
  2. 02同じセッションで国内外のサイトを閲覧
  3. 03エージェントがVPN利用中にバックエンド通信をISP経由にする

MCP 対応

Playwright MCPサーバーが専用プロキシを起動・管理し、ホストごとにブラウザー接続を振り分けます。MCPクライアントは、指定ホストをISP経由、それ以外をVPNトンネル経由にしてブラウジングできます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"farshadmomo-lan-direct": {
"command": "npx",
"args": [
"-y",
"lan-direct"
]
}
}
}
起動コマンドnpx -y lan-direct

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npmlan-direct1.0.2

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

lan-direct

check npm license

フルトンネル VPN を使っているコーディングエージェント(Claude Code と Codex)向けのスキルとブラウザー MCPです。

エージェントが API にアクセスするためには、VPN をオンにしたままにする必要があります。しかし、テスト対象のアプリが呼び出すサービスは、VPN の国外出口 IP を拒否します。たとえば、国内 API、決済や SMS のゲートウェイ、銀行のエンドポイントなどです。VPN をオフにすることはできません。エージェントとの接続が切れてしまうためです。

lan-direct は、エージェントはトンネルに接続したまま、アプリには ISP 経由の直接経路を提供します。管理者権限も、ルーティングテーブルの編集も、VPN の再設定も不要です。仕組み。

インストール

Node ≥ 20.6 が必要です。Windows では PowerShell、Linux/macOS では bash と curl も必要です。管理者権限、シンボリックリンク、名前の変更は不要です。

npm から
npm install -g lan-direct
lan-direct install-skill                                             # or --codex
claude mcp add playwright-split --scope user "--" npx -y lan-direct browser

次にエージェントを再起動します。これだけです。どのプラットフォームでも同じ 3 行です。

どの方法でインストールした場合も、MCP コマンドには npx -y lan-direct browser のほうがおすすめです。チェックアウト先が移動しても使えますが、クローン内への絶対パスは移動すると使えなくなります。

"--" を引用符で囲む理由。 Windows では claude が claude.ps1 に解決されます。PowerShell のパラメーターバインダーは、スクリプトに渡される前に引用符のない -- を取り除きます。そのため CLI は -y を自身のフラグとして読み込み、error: unknown option '-y' で失敗します。引用符で囲めばこれを防げます。また、bash では引用符は処理に影響しないため、同じ行が PowerShell、bash、cmd で使えます。

クローンから

スキルを編集したい場合や、変更を追跡したい場合はこちらがおすすめです。git pull 1 回ですべてを更新できます。一方、npm ではファイルをリンクせずにコピーするため、npm update -g lan-direct && lan-direct install-skill が必要です。

どちらの方法でも、独自のホスト一覧 ~/.lan-direct-hosts は変更されません。

1. エージェントのスキルディレクトリにクローンします。 どちらのエージェントも、ディレクトリをスキャンして SKILL.md を探します。スキャンするディレクトリはそれぞれ異なります。

# Windows - Claude Code
git clone https://github.com/farshadmomo/lan-direct.git "$HOME\.claude\skills\lan-direct"

# Windows - Codex
New-Item -ItemType Directory -Force -Path "$HOME\.agents\skills" | Out-Null
git clone https://github.com/farshadmomo/lan-direct.git "$HOME\.agents\skills\lan-direct"
# Linux / macOS - Claude Code
git clone https://github.com/farshadmomo/lan-direct.git ~/.claude/skills/lan-direct

# Linux / macOS - Codex
mkdir -p ~/.agents/skills
git clone https://github.com/farshadmomo/lan-direct.git ~/.agents/skills/lan-direct

2. ブラウザー MCP を登録します。

powershell -NoProfile -ExecutionPolicy Bypass `
  -File "$HOME\.claude\skills\lan-direct\scripts\install.ps1"

インストーラーはバイパスが実際に機能することを確認し、サーバーをこのチェックアウト先に登録して、Codex 用の同等の ~/.codex/config.toml ブロックを表示します。安全に再実行できます。既存のエントリーを置き換えるため、重複しません。

Linux/macOS にはインストーラースクリプトがありません。直接登録してください。

claude mcp add playwright-split --scope user "--" \
  node ~/.claude/skills/lan-direct/scripts/lan-browser.mjs --port 8900

エージェントを再起動します。 その後、Claude Code では /lan-direct を使うか、どちらのエージェントでも問題を説明してください。description のフロントマターがトリガーとなり、「VPN をオンにしたままこれをテストして」や「API が VPN の IP を拒否する」のような表現に反応します。

更新するには、git -C <that directory> pull を実行します。再インストールは不要です。

1 つのクローンから両方のエージェントを使う

一度クローンし、もう一方の場所にリンクします。Windows では、シンボリックリンクと違い、管理者権限や Developer Mode がなくてもジャンクションを使えます。

git clone https://github.com/farshadmomo/lan-direct.git "$HOME\.claude\skills\lan-direct"
New-Item -ItemType Directory -Force -Path "$HOME\.agents\skills" | Out-Null
cmd /c mklink /J "$env:USERPROFILE\.agents\skills\lan-direct" "$env:USERPROFILE\.claude\skills\lan-direct"

macOS/Linux:

git clone https://github.com/farshadmomo/lan-direct.git ~/.claude/skills/lan-direct
mkdir -p ~/.agents/skills
ln -s ~/.claude/skills/lan-direct ~/.agents/skills/lan-direct

あとは git pull 1 回で両方を更新できます。

別の場所にインストールする(スキルを編集する場合)

任意の場所にクローンし、スキルディレクトリ内にリンクします。ジャンクションには管理者権限は不要です。シンボリックリンクには、昇格したシェルまたは Developer Mode が必要です。

git clone https://github.com/farshadmomo/lan-direct.git "D:\projects\lan-direct"
cmd /c mklink /J "$env:USERPROFILE\.claude\skills\lan-direct" "D:\projects\lan-direct"

インストール方法にかかわらず、スキルフォルダー内のディレクトリ名は必ず lan-direct にしてください。どちらのエージェントもディレクトリ名で検出するため、SKILL.md の name: と一致させる必要があります。

## ISP 経由で接続するホスト

ルールは lan-hosts.txt にあり、サフィックス一致で判定されます。

.ir             every .ir host
digikala.com    also seller.digikala.com, api.digikala.com, ...

一致しないホストはすべてトンネルを経由します。 国内のホストだけを追加してください。海外のホストを追加すると、フィルタリングされる可能性のある ISP 経由で接続されます。

同梱のリストには、.ir 全体に加えて、ほかの TLD を利用しているイランのサービスも含まれています。決済(zarinpal、payping、nextpay)、SMS/OTP(kavenegar、melipayamak、farazsms、ippanel)、ホスティング(parspack、hostiran、mizbanfa)、地図(neshan)、コマース(digikala、torob、basalam)、教育および求人(quera、faradars、maktabkhooneh、7learn、irantalent)、AI(hoosha、gapgpt)、およびこれらのサイトに埋め込まれている分析用ドメイン(najva、yektanet)です。すべて確認済みで、トンネル経由では到達できず、ISP 経由では応答します。

独自のホストを追加する

~/.lan-direct-hosts に、同じ形式で1行に1つずつ追加してください。

# my own
aparat.com
internal.corp

このファイルは git pull の影響を受けず、ブラウザーの起動時に毎回読み込まれるため、再インストールは不要です。ブラウザー以外を再起動する必要もありません。3つのソース、つまり同梱ファイル、独自ファイル、および起動時に渡された --lan-hosts a,b のルールがすべて統合されます。

ルールを間違えると、サイトがダウンしているように見える形で失敗します。そのため、プロキシは接続ごとに選択した経路を表示します。サイトを疑う前に確認してください。または、何も起動せずに直接確認することもできます。

$ lan-direct route hoosha.com youtube.com api.anthropic.com
24 rules in effect

  hoosha.com                       lan    ISP (bound)
  youtube.com                      vpn    tunnel
  api.anthropic.com                vpn    tunnel

同梱内容

2つの要素が一緒にインストールされます。

機能
スキル(SKILL.md)検出、検証、スタックごとの仕組みの選択、終了処理まで、ワークフロー全体をエージェントに教えます。SKILL.md を検索して自動的に検出されます。
ブラウザー MCP(lan-browser.mjs)独自のプロキシを起動して管理する Playwright MCP サーバーです。ホストごとに経路を振り分け、1つのブラウザーセッション内で国内サイトは ISP 経由、それ以外はトンネル経由で接続します。

ブラウザーでのアクセスを可能にするのは MCP です。Chromium には送信元をバインドするフラグがないため、ブラウザーが ISP に接続するにはプロキシが必要です。これがなければ、スキルはバックエンドや CLI を対象にしますが、ページには対応できません。

仕組み

ソケットごとの送信元アドレスバインドを使用します。物理アダプターの IP に明示的にバインドされたソケットは、トンネルではなく、そのアダプターのデフォルトルートを使用します。

$ curl -s https://api.ipify.org                            # 203.0.113.7    (VPN exit)
$ curl -s --interface 192.168.1.20 https://api.ipify.org   # 198.51.100.42  (real ISP)

管理者権限も、ルーティングテーブルの編集も、VPN の再設定も不要で、システム全体に影響する設定もありません。ソケットごとの設定なので、明示的にオプトインする仕組みになっています。設定を要求しないプロセスが影響を受けることはありません。この特性により、エージェントはトンネル経由の接続を維持できます。

これは意図的に route add を使いません。静的ルートはシステム全体に適用されるため、その宛先への接続がすべてトンネルから外れ、エージェントも対象になります。また、管理者権限も必要です。

サーバープロセスには --interface フラグがないため、設定方法は2つあります。

バックエンド仕組み
Node / Next.jslan-bind.mjs — プロセス内のすべてのソケットをバインドする --import プリロード
その他すべてlan-proxy.mjs — 送信ソケットをバインドするローカルプロキシ。HTTP_PROXY を使って制御します

Node の落とし穴

バックエンドが Node の場合、HTTP_PROXY は機能せず、エラーも表示されません。

ネイティブの fetch は Node 組み込みの undici 上で動作しますが、Node ≤ 23 ではプロキシ環境変数を無視し、https.Agent も受け付けません。Node 22.20 で検証したところ、通常の環境変数、NODE_USE_ENV_PROXY=1、--use-env-proxy はいずれも機能せず、VPN 経由で通信が行われる間もプロキシのログは空のままでした。これは Next.js、openai SDK、およびネイティブの fetch を使うその他すべてに影響します。

lan-bind.mjs はプリロードで net/tls にパッチを適用し、組み込みの undici にも対応します。ネイティブの fetch、openai SDK、axios、node-fetch、got、および通常の http/https を一括でカバーします。依存関係もプロキシプロセスも HTTP_PROXY も不要です。NODE_OPTIONS は fork されたワーカーにも引き継がれるため、Next.js や Vite の開発サーバーにも対応します。

ループバック宛ての接続は意図的に対象外にします。LAN IP を送信元にしたソケットでは 127.0.0.1 に接続できないため、この保護がないと、ローカルの Redis/Postgres/Mongo を使うアプリは EADDRNOTAVAIL で動作しなくなります。

手動での使用

以下のすべてのパスでは、インストール先を $skill と表記します。

$skill = "$HOME\.claude\skills\lan-direct"    # Claude Code
$skill = "$HOME\.agents\skills\lan-direct"    # Codex

1. 検出と検証。 バイパスが実際に機能する場合にのみ、終了コード 0 で終了します。

powershell -NoProfile -ExecutionPolicy Bypass -File "$skill\scripts\lan-detect.ps1"
bash ~/.claude/skills/lan-direct/scripts/lan-detect.sh    # Linux / macOS

lanIp、gateway、lanDns、subnet、tunnelActive、vpnAdapter、directEgress、 lanEgress、fakeIpDns、bypassWorks を出力します。推測ではなく、2 回プローブして比較します。 バイパスが機能しない場合は処理を続行しないため、誤って成功と判定されることはありません。

2a. Node バックエンド。 そのままコピーして貼り付けてください。入力が必要なのは lanIp だけです。

$env:LAN_BIND     = "<lanIp>"
$env:NODE_OPTIONS = "--import file:///$($skill -replace '\\','/')/scripts/lan-bind.mjs"
npm run dev

Git Bash から同じ操作をする場合は、パスを明示します。

LAN_BIND=<lanIp> \
NODE_OPTIONS="--import file:///C:/Users/YOU/.claude/skills/lan-direct/scripts/lan-bind.mjs" \
npm run dev

Windows では --import にスラッシュを使った絶対 file:// URL が必要です。Windows のパスをそのまま指定すると失敗します。

2b. それ以外。 プロキシを起動します。

node "$skill\scripts\lan-proxy.mjs" --bind <lanIp> --self-test    # run with the tunnel UP
node "$skill\scripts\lan-proxy.mjs" --bind <lanIp> --port 8899

次に、HTTP_PROXY=http://127.0.0.1:8899、 HTTPS_PROXY=http://127.0.0.1:8899、NO_PROXY=localhost,127.0.0.1,<subnet> を指定して バックエンドを起動します。

HTTP_PROXY だけでは不十分なスタックについては、SKILL.md を参照してください。特に Apache 上の PHP では、 サービスがシェル環境を引き継がず、libcurl から環境変数が見えません。

2 つのネットワークを同時にブラウジングする

どちらか一方が、もう一方のすべてを網羅しているわけではありません。海外のトンネル経由でイランの ISP に接続した場合の測定結果です。

VPN 経由ISP 経由
youtube、x、facebook、telegram、reddit使用可能接続不可
hoosha、neshan、avalai接続不可使用可能
github、google、npm使用可能使用可能
api.anthropic.com使用可能403

最後の行が、エージェントをトンネルから決して移動してはならない理由です。移動すると、エージェントは完全に動作しなくなります。

ブラウザー MCP は、1 つのセッションでこの両方を処理します。Chrome には すべて をプロキシに送信するよう指示し、独自のルーティング判断はさせません。プロキシは各 CONNECT からホスト名を読み取り(TLS の前に平文で確認できます)、次のように判断します。

useBind(host) ? net.connect({ host, port, localAddress })   // ISP
              : net.connect({ host, port })                  // tunnel

「VPN を使う」コードパスはありません。行うのはバインドだけです。これを省略すると OS のルーティングテーブルが適用され、トンネルがそのルートを所有します。LAN はオプトインです。それ以外の場合はトンネルが使われます。

これはセッション単位ではなく、接続単位で適用されます。同じ ページ からの 2 つの fetch 呼び出しでも、物理的に異なるルートを通る場合があります。1 つのタブ内の 1 ページで測定した結果は次のとおりです。

リクエスト外部への経路
api.hoosha.com(リストに記載)ISP
api.ipify.org(リストに未記載)VPN

プロキシの各ログ行には、選択したルートが記録されます。

CONNECT  lan  hoosha.com:443
CONNECT  vpn  youtube.com:443

ブラウザーのプロキシは 8900 で動作します。これは、上記のバックエンドテストに使う 8899 とは意図的に分けています。MCP は自分のポートですでに待ち受けているものを再利用するため、同じ番号を使うと、すべてにバインドするバックエンドプロキシがブラウザーをひそかに捕捉し、全トラフィックを ISP 経由に流す可能性があります。その結果、トンネルが必要なサイトがまさに利用できなくなります。

内容

ファイル用途
SKILL.mdスキルの内容:ワークフロー、スタック別の手順、トラブルシューティング
lan-hosts.txtISP 経由でルーティングするホスト。自分のホストは ~/.lan-direct-hosts に追加します
scripts/install.ps1このチェックアウトにブラウザー MCP を登録します。再実行しても安全です
scripts/lan-detect.ps1物理アダプターを見つけ、バイパスが機能することを証明します。JSON を出力します
scripts/lan-detect.shLinux と macOS 用の同じスクリプトです。同じ JSON、同じ終了コードの仕様です
scripts/lan-bind.mjsNode のプリロード。プロセス全体をバインドします。Node/Next.js 用の手段です
scripts/lan-proxy.mjs依存関係のない HTTP/CONNECT プロキシ。ホストごとのルーティングを任意で設定できます
scripts/lan-browser.mjsMCP サーバー。Playwright と、起動して管理するプロキシを備えています
scripts/lan-route.mjsルーティングルール。インポートしてテストできます。ライブラリーとしてもエクスポートされます
bin/lan-direct.mjsCLI:detect、proxy、browser、route、install-skill
test/npm test:ルーティング、ルールの解析、プロキシ、プリロードをテストします

Node ≥ 20.6 と curl が必要です(Windows 10 以降には組み込まれており、他の環境では標準で利用できます)。依存関係はありません。

開発

npm test          # node:test, no install step - there are no dependencies

テストは34件あります。ルーティングの判定条件は、ここで唯一、失敗しても表面化しないロジックなので、特に重点的にテストしています。誤った判定ではエラーもログも出ないまま、トラフィックが誤った物理ネットワークへ送られてしまいます。検出対象の2つの変異について、どちらもテストスイートが失敗することを確認しています。1つは単純なendsWith(そのため、evilhoosha.comがhoosha.comに一致します)、もう1つはループバックのチェック漏れです。

プリロードは、LAN_BINDに192.0.2.1を設定した実際の子プロセスでテストします。これはマシンに割り当てられないアドレスなので、ソケットのバインドは即座に失敗します。これにより、パッチが何もせずに静かに終わっているのではなく、実際に有効であることを確認できます。

CIでカバーできないのは、稼働中のトンネルと物理アダプターが必要なlan-proxy.mjs --self-testです。VPNを接続して、手動で実行してください。変更内容はCHANGELOG.mdに記載されています。

古いランタイムをお使いの場合の注意点です。Node 20.6.0ではテストスイートを実行できません。すべてのアサーションに合格したあと、テストランナーが終了しなくなります。これはそのリリースのランナーのバグであり、lan-directのバグではありません。lan-direct自体は問題なく動作します。現行の20.xまたは22であれば問題ありません。

補足

  • プロキシは127.0.0.1のみで待ち受けます。より広い範囲にバインドすると、LANにオープンプロキシを公開することになります。
  • lan-direct route <host>を実行すると、統合済みのルールリストに基づいて、ホストがどのネットワーク経由で送信されるかを確認できます。ブラウザーを起動して調べるより高速です。
  • .ps1ファイルは意図的にASCIIのみで記述しています。Windows PowerShell 5.1はBOMなしのUTF-8をANSIとして読み込み、紛れ込んだem dashがあるとパーサーでエラーになります。CIでこれをチェックしています。
  • フェイクIPのDNS(sing-box、clash)を使用する場合は、--dns <lanDns>を渡してください。dns.setServers()はdns.lookup()には影響しません。dns.lookup()はトンネルが制御するOSのリゾルバーを経由します。
  • Git Bashからpkill -f lan-proxyを実行しても、Windowsのnode.exeは終了しません。SKILL.mdにあるPowerShellの終了手順を使ってください。

検証環境

Windows 11、Node 22.20、Intel Wi-Fi上のnekoray / sing-box TUNで検証しました。実際のNext.js 16アプリから、イランの地図サービスであるNeshanとLLMゲートウェイのAvalAIを呼び出し、エンドツーエンドでテストしました。どちらも外国のIPアドレスからの接続を拒否します。

VPN経由ISP経由
AvalAI /models、/chat/completionsECONNRESET200、実際の応答とトークン使用量
Neshanの逆ジオコーディング応答なし200、正しい住所
Neshanのルート検索/ジオコーディング応答なし200
Next.js /api/reverse、/api/chat—200、フルスタック経由のライブデータ

ブラウザーMCPも同じ方法でテストしました。国内のAIプラットフォームとYouTubeを同じセッション内で続けて開き、国内サイト独自のCDNでISPのIPアドレスと国コードIRが報告される一方、YouTubeはトンネル経由でドイツ語ロケールの画面を表示しました。

エージェント自身の接続は、全期間を通してトンネル経由のままでした。

アダプターの検出方法は汎用的です。WindowsではGet-NetAdapter -Physical、Linuxではsysfsのdeviceシンボリックリンク、macOSではnetworksetupを使用するため、WireGuard、OpenVPN、WARPなどでも動作するはずです。ただし、lan-detectは推測せず、実際に検証します。検証できない場合はゼロ以外の終了コードを返します。

プラットフォームの状況。 Windowsはエンドツーエンドでテスト済みの環境です。lan-detect.shはLinux(Ubuntu 24.04)でも実行し、正しいインターフェース、ゲートウェイ、DNS、ルート、終了コードを返すことを確認しました。ただし、これは独自のトンネルを持たないマシンでのテストのため、バイパス検証済みの分岐は未検証です。macOS版はnetworksetup/ipconfig/netstatの文書化された動作に基づいて実装していますが、まだ一度も実行していません。どちらも推測で進めずに処理を中止するため、失敗時にはVPN経由の通信が黙って続くのではなく、明確なエラーが表示されます。報告をお待ちしています。

Linux固有の注意点もあります。Windowsとは異なり、送信元アドレスをバインドするだけではルーティングテーブルを上書きできないため、ポリシールーティングを使用するトンネルでは、バインド後もトラフィックがトンネル経由になる場合があります。これは2つのプローブで検出します。そのような場合、lan-detect.shは成功を報告せず、その旨と修正方法を示します。

未検証の項目として、lan-detectの「キルスイッチを検出」する分岐があります。テストマシンでは再現できなかったVPNの状態が必要です。

ライセンス

MIT — LICENSEを参照してください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。