mcpField
L
lan-direct

lan-direct

本地服务
github.com/farshadmomo浏览器自动化412 周前更新

关于 lan-direct

lan-direct 为使用全隧道 VPN 的编码 Agent 提供浏览器 MCP 服务和技能。其代理按主机名分流:指定主机经 ISP 连接,其他浏览器流量及 Agent 保持在 VPN 隧道中。

主要功能

  1. 01按主机名路由浏览器连接
  2. 02让指定主机经 ISP 连接
  3. 03未匹配流量保留在 VPN 隧道
  4. 04提供 Playwright MCP 服务和 Agent 技能
  5. 05添加并检查主机路由规则

适用场景

  1. 01测试会拒绝 VPN IP 的服务所调用的应用
  2. 02在同一浏览器会话访问境内外网站
  3. 03Agent 使用 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 环境下的编码 Agent 提供的技能和浏览器 MCP——适用于 Claude Code 和 Codex。

你必须保持 VPN 开启,因为 Agent 需要通过它访问自己的 API。但你正在测试的应用会调用拒绝 VPN 外部出口 IP 的服务:国内 API、支付或短信网关、银行接口。关闭 VPN 不可行——那会切断 Agent 的连接。

lan-direct 为应用提供 ISP 直连路径,同时让Agent 保持在隧道中。无需管理员权限,不用编辑路由表,也不必重新配置 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

然后重启 Agent。就这么简单——所有平台都使用相同的三行命令。

无论你采用哪种安装方式,npx -y lan-direct browser 都是更好的 MCP 命令:它不受检出目录移动的影响,而指向克隆目录的绝对路径则会受影响。

为什么要给 "--" 加引号。 在 Windows 上,claude 会解析为 claude.ps1,PowerShell 的参数绑定器会在脚本看到裸 -- 之前将其剥离。随后 CLI 会把 -y 当作自己的标志读取,并报错 error: unknown option '-y'。加引号可以避免这个问题,而且在 bash 中引号不起作用——因此同一行命令可用于 PowerShell、bash 和 cmd。

从克隆安装

如果你想编辑或跟踪技能,建议使用这种方式——只需执行一次 git pull 就能更新所有内容;使用 npm 时则需要执行 npm update -g lan-direct && lan-direct install-skill,因为 install-skill 会复制文件,而不是创建链接。

无论采用哪种方式,都不会触碰你自己的主机列表 ~/.lan-direct-hosts。

1. 克隆到 Agent 的技能目录。 两个 Agent 都会扫描目录中的 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

重启 Agent。 然后在 Claude Code 中使用 /lan-direct;或者在任一 Agent 中直接描述问题——description frontmatter 是触发条件,会对“在 VPN 开启时测试这个”或“API 拒绝 VPN IP”等说法作出响应。

更新方法:git -C <that directory> pull。无需重新安装。

从单个克隆同时使用两个 Agent

克隆一次,然后为第二个位置创建链接。在 Windows 上,目录联接无需管理员权限或开发者模式即可使用,不像符号链接:

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 即可同时更新两处。

安装到其他位置(用于编辑技能)

将仓库克隆到任意位置,然后创建链接。目录联接无需管理员权限;符号链接则需要提升权限的 shell 或开发者模式:

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——两个 Agent 都根据目录名称发现技能,而且该名称必须与 SKILL.md 中的 name: 匹配。

## 哪些主机通过 ISP 访问

规则位于 lan-hosts.txt 中,采用后缀匹配:

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

未匹配的主机都会走隧道。 只列出国内主机——添加国外主机会让流量经由可能会过滤内容的 ISP 发出。

随附列表涵盖所有 .ir 域名,以及使用其他顶级域名的伊朗服务: 支付(zarinpal、payping、nextpay)、短信/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,每行一条,格式相同:

# my own
aparat.com
internal.corp

git pull 永远不会改动此文件,并且每次浏览器启动时都会读取——无需重新安装,也无需重启浏览器以外的任何东西。三个来源的规则会合并:随附文件、你的文件,以及启动时传入的任何 --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

包含内容

分为两部分,安装时会一并安装:

功能
技能(SKILL.md)教会 Agent 完整的工作流程——检测、验证、按技术栈选择机制、清理。通过扫描 SKILL.md 自动发现。
浏览器 MCP(lan-browser.mjs)一个 Playwright MCP 服务,会启动并管理自己的代理,且按主机路由:国内网站通过 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,也不会影响全局。由于这是按套接字生效的,因此默认就是选择性启用——不请求此功能的进程不会受到影响。这一特性确保 Agent 始终使用隧道。

这里特意不使用 route add。静态路由是全局的:它会让所有进程(包括 Agent)访问该目标时绕过隧道,而且需要管理员权限。

服务进程没有 --interface 标志,因此有两种方式可以为它指定接口:

你的后端机制
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 会传递给派生的工作进程,因此也适用于 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。它会探测两次并进行比较,而不是想当然地假设绕过有效—— 如果绕过未生效,则拒绝继续,因此绝不会误报通过。

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, 因为服务不会继承你的 shell 环境,libcurl 也看不到这些变量。

同时浏览两个网络

两种路径互不包含对方的能力。在使用外国隧道的伊朗 ISP 上进行测量:

经 VPN经 ISP
youtube、x、facebook、telegram、reddit可用无法访问
hoosha、neshan、avalai无法访问可用
github、google、npm可用可用
api.anthropic.com可用403

最后一行就是为什么绝不能让 Agent 离开隧道——一旦这么做,Agent 就会完全停止工作。

浏览器 MCP 会在一个会话中处理这种混合情况。Chrome 被设定为将所有流量发送到代理, 自身不做路由决策;代理会从每个 CONNECT 中读取主机名(TLS 握手前以明文传输),然后作出决定:

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

代码中没有“使用 VPN”的路径。唯一执行的操作是绑定——跳过它,操作系统路由表就会生效,而隧道拥有该路由表。LAN 路由需主动启用;否则默认使用隧道。

路由按连接决定,而非按会话决定。同一页面中的两次 fetch 调用可以经过不同的物理路由——以下是在同一标签页的同一页面中测得的结果:

请求出口
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.txt经 ISP 路由的主机名。你的主机名应添加到 ~/.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 项测试。路由判定逻辑受到最多关注,因为这里的逻辑只有它出错时不会显现——错误匹配会将流量发送到错误的物理网络,既没有报错,也不会产生日志。它旨在捕获的两种变更都已验证会导致测试套件失败:简单使用 endsWith(因此 evilhoosha.com 会匹配 hoosha.com),以及缺少环回地址检查。

预加载脚本在真实的子进程中测试,并设置了 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-direct route <host> 会根据合并后的规则列表显示某个主机的流量将通过哪个网络发出。比启动浏览器查看快得多。
  • .ps1 文件刻意只使用 ASCII 字符:Windows PowerShell 5.1 会将无 BOM 的 UTF-8 作为 ANSI 读取,而一个多余的长破折号就会导致解析器出错。CI 会对此进行检查。
  • 使用 fake-IP DNS(sing-box、clash)时,请传入 --dns <lanDns>。dns.setServers() 不会影响 dns.lookup(),后者会经由隧道控制的操作系统解析器进行解析。
  • 在 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(伊朗地图服务)和 AvalAI(大模型网关),二者都会直接拒绝来自国外 IP 的请求:

经由 VPN经由 ISP
AvalAI /models、/chat/completionsECONNRESET200,返回真实补全结果和 token 用量
Neshan 反向地理编码无响应200,返回正确地址
Neshan 路由 / 地理编码无响应200
Next.js /api/reverse、/api/chat—200,全栈返回实时数据

浏览器 MCP 也以同样方式进行了测试:在一个会话中先后打开一个国内 AI 平台和 YouTube;国内网站自身的 CDN 报告了 ISP 地址和国家代码 IR,同时 YouTube 则通过隧道呈现其德语区域版本的页面框架。

Agent 自身的连接始终走隧道。

适配器发现方式是通用的——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 上那样覆盖路由表,因此使用策略路由的隧道可能会继续承载该流量,即使流量已经绑定了源地址。这正是两项探测要检测的情况——如果发生,lan-detect.sh 会明确指出并给出修复方法,而不会报告成功。

尚未验证的还有:lan-detect 的“检测到 kill-switch”分支,因为测试机器无法将 VPN 设置为所需状态。

许可证

MIT——详见 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。