内容
# 🌐 tplink-archer-mcp
> **用简单的中文与你的 TP-Link 路由器对话。**
> 一个模型上下文协议(MCP)服务器,暴露了 117 个用于家庭路由器读写操作的工具——WiFi、LAN、NAT、安全、VPN等。
[](https://opensource.org/licenses/MIT)
[](https://www.python.org/downloads/)
[](https://modelcontextprotocol.io/)
[]()
```
你: "显示当前连接到我路由器的所有设备"
克劳德: [调用 js_get_dhcp_clients] → 14 个设备,以下是 IP 地址和 MAC 地址列表
你: "添加一个 8080 端口转发到 192.168.0.50 TCP"
克劳德: [调用 js_add_port_forward(...)] → ✅ 规则已添加
你: "查看当前的 PPPoE 配置——我的用户名是对的吗?"
克劳德: [调用 js_get_pppoe_config] → 用户名=sharoz_dawa, 拨号模式=自动, MTU=1480
你: "为 MAC 地址为 34-2E-B7-9F-40-75 的设备保留 192.168.0.41"
克劳德: [调用 js_add_dhcp_reservation(...)] → ✅ 静态租约已创建
```
无需点击网页界面。无需记住每个设置在菜单中的位置。只需询问。
---
## 🚀 为什么存在
每个现代 TP-Link 路由器都运行一个 Vue.js 单页网页界面,锁定每个 API 调用:
1. AES-CBC 加密(每会话密钥)
2. HMAC-SHA256 签名请求
3. 登录时使用 RSA 密码握手
4. 回调注册表拒绝来自第三方客户端的许多端点
流行的 `tplinkrouterc6u` Python 库处理身份验证和约 10 个端点,但 AX53 的固件拒绝了其中 80% 的其他端点。那么,如何从脚本中读取 DHCP 保留或更改 DNS?
**突破:** 同样为网页界面提供支持的 JavaScript 导出一个 `store` 对象,包含 `read/write/insert/remove/update` 方法。通过在无头浏览器中使用 `page.evaluate` 动态导入块,可以调用与网页界面相同的 API——相同的加密、相同的身份验证、相同的回调。**每个端点,解密后,从 Python 可访问。**
此 MCP 封装了所有这些工具,共 117 个,任何 Claude/Cursor/MCP 客户端都可以调用。
---
## 📡 支持的路由器
### ✅ 确认有效
| 型号 | 测试固件 | 备注 |
|---|---|---|
| **TP-Link Archer AX53** (AX3000) | `1.11.0_2026-01-05` | 主要开发目标 |
### 🟡 可能有效(相同的固件系列)
JS 直接后端适用于任何 TP-Link 路由器,该路由器配备了 **现代 Vue 网页界面** 和 `update-store` 模块。其中包括:
- **Archer AX 系列:** AX10、AX20、AX23、AX55、AX73、AX75、AX90、AX95、AXE5400、AXE16000
- **Archer A 系列:** A6、A7、A8、A9、A10、A20
- **Archer C 系列:** C6、C20、C50、C80、C1200、C3200、C5400X
- **Archer GX 系列:** 游戏专注型号,相同界面
遗留的 `tplinkrouterc6u` 库后端扩展兼容性到:
- **Mercusys 路由器** 家族(重新品牌化的 TP-Link 硬件)
- **TP-Link Deco** 网状系统
- **TP-Link MR 系列** (LTE/4G)
- **TP-Link VR 系列** (DSL)
- **TP-Link EX 系列** (旧 AX 固件)
- **TP-Link XDR 系列**
- **TP-Link RE 系列** (范围扩展器)
- **TP-Link CPE/EAP/SG** (企业设备)
如果您的型号未列出,通用逃脱工具(`js_read`、`js_write`)可能仍然有效——只需指向正确的端点。
### ❌ 不支持
- **Tapo** 路由器(不同的固件系列 - 它们使用 Tapo 云 API)
- 运行自定义固件的路由器(OpenWrt、DD-WRT 等 - 它们有自己的 API)
---
## ⚡ 快速入门
### 1. 安装
```bash
git clone https://github.com/sharozdawa/tplink-archer-mcp
cd tplink-archer-mcp
uv sync
uv run playwright install chromium
```
要求:
- Python 3.12+
- [`uv`](https://github.com/astral-sh/uv) (快速 Python 包管理器)
- 网络上的 TP-Link Archer 路由器
- 路由器管理员密码
### 2. 存储路由器密码
**macOS** (推荐 - 使用钥匙串):
```bash
security add-generic-password -s "tplink-archer-mcp" -a "192.168.0.1" -w "<YOUR_ADMIN_PASSWORD>" -U
```
**其他平台** (环境变量):
```bash
export TPLINK_ARCHER_PASSWORD="..."
export TPLINK_ARCHER_HOST="192.168.0.1" # 默认
export TPLINK_ARCHER_USERNAME="admin" # 默认
```
### 3. 测试是否有效
```bash
uv run python -c "
import asyncio
from tplink_archer_mcp import tools_js as js
from tplink_archer_mcp.js_backend import close_js_backend
async def go():
print(await js.js_get_wan_status())
await close_js_backend()
asyncio.run(go())
```
您应该看到您的 WAN IP、DNS、网关等已打印出来。
### 4. 在 Claude Code 中注册(或任何 MCP 客户端)
编辑 `~/.claude.json`:
```json
{
"mcpServers": {
"tplink-archer": {
"type": "stdio",
"command": "uv",
"args": [
"run", "--python", "3.12",
"--directory", "/absolute/path/to/tplink-archer-mcp",
"tplink-archer-mcp"
]
}
}
}
```
重启 Claude Code。117 个工具出现在 `tplink-archer` 命名空间下。
### 5. 与其对话
```
"我的网络上有哪些设备?"
"显示我的端口转发规则"
"我的当前 WiFi 5G 配置是什么?"
"为 MAC 地址 AA-BB-CC-DD-EE-FF 的设备添加 DHCP 保留,IP地址为 192.168.0.50"
"禁用 WAN ping 响应"
"在 5GHz 上启用 MU-MIMO"
"我的 PPPoE 用户名是什么?"
```
---
## 🛠️ 您能做什么
### 读取路由器状态的每个方面
| 区域 | 工具 | 返回 |
|---|---|---|
| WAN 状态 | `js_get_wan_status` | 公共 IP、网关、子网掩码、DNS |
| PPPoE 配置 | `js_get_pppoe_config` | 用户名、MTU、连接模式、IP 模式 |
| LAN 设置 | `js_get_lan_config` | LAN IP、子网掩码、MAC、DHCP DNS |
| DHCP 服务器 | `js_get_dhcp_server` | 范围、租期、网关、DNS |
| DHCP 租约 | `js_get_dhcp_clients` | 当前租用的 IP(活动设备) |
| DHCP 保留 | `js_get_dhcp_reservations` | 静态 IP 绑定 |
| 端口转发 | `js_get_port_forwards` | 所有虚拟服务器规则 |
| 端口触发器 | `js_get_port_triggers` | 端口触发规则 |
| DMZ | `js_get_dmz` | DMZ 启用 + 主机 |
| UPnP | `js_get_upnp` | UPnP 启用 + 活动映射 |
| ALG | `js_get_alg` | FTP、H323、IPSec、L2TP、PPTP、RTSP、SIP、TFTP 开关 |
| 防火墙 | `js_get_firewall` | 启用 + LAN/WAN ping 响应 |
| 访问控制 | `js_get_access_control` | 模式 + 阻止设备 |
| WiFi(每个频段) | `js_get_wifi(band)` | SSID、密码、频道、加密、MU-MIMO 等 |
| 智能连接 | `js_get_smart_connect` | 频段引导启用 |
| EasyMesh | `js_get_easymesh` | 网状启用 + 连接节点 |
| WireGuard 服务器 | `js_get_wireguard_server` | 内置 WireGuard 配置 |
| IPv6 | `js_get_ipv6` | IPv6 状态 + 地址 |
| 固件 | `js_get_firmware` | 型号、硬件版本、固件版本 |
| 调度重启 | `js_get_scheduled_reboot` | 自动重启计划 |
### 更改 UI 中可以更改的任何内容
| 区域 | 工具 | 执行操作 |
|---|---|---|
| WiFi 密码 | `js_set_wifi_password(band, password)` | 更改 PSK |
| WiFi SSID | `js_set_wifi_ssid(band, ssid)` | 重命名网络 |
| WiFi 安全 | `js_set_wifi_security(band, mode)` | wpa2 / wpa2_wpa3 / wpa3 / open |
| WiFi 频道 | `js_set_wifi_channel(band, channel, htmode)` | 特定频道 + 宽度 |
| WiFi 功能 | `js_set_wifi_features(band, mu_mimo, airtime_fairness, hidden, enable)` | 开关 |
| OFDMA / TWT | `js_set_ofdma`, `js_set_twt` | Wi-Fi 6 功能 |
| 智能连接 | `js_set_smart_connect(enable)` | 频段引导 |
| DNS(LAN) | `js_set_lan_dns(pri_dns, snd_dns)` | 覆盖 DHCP 公告的 DNS |
| DHCP 服务器 | `js_set_dhcp_server(enable, leasetime_min, pri_dns, snd_dns)` | 服务器配置 |
| DHCP 保留 | `js_add_dhcp_reservation(mac, ip, name)` | 绑定设备 IP |
| 端口转发 | `js_add_port_forward(name, ext_port, int_port, ip, protocol)` | 打开端口 |
| DMZ | `js_set_dmz(enable, ipaddr)` | DMZ 主机 |
| UPnP | `js_set_upnp(enable)` | UPnP 开关 |
| ALG | `js_set_alg(ftp=, h323=, ...)` | 按协议开关 |
| 防火墙 | `js_set_firewall(enable, lan_ping, wan_ping)` | 防火墙 + ping |
| EasyMesh | `js_set_easymesh(enable)` | 网状开启/关闭 |
| 调度重启 | `js_set_scheduled_reboot(enable, cycle, day, time)` | 自动重启 |
| 立即重启 | `js_reboot_now()` | 重启路由器 |
| PPPoE | `js_set_pppoe(username, password, pri_dns, snd_dns, dns_mode, mtu)` | WAN PPPoE 配置 |
### 通用逃脱孔
对于任何尚未封装为类型化工具的内容:
```python
js_read("/admin/network?form=wan_ipv4_pppoe")
js_write("/admin/nat?form=dmz", {"enable": "on", "ipaddr": "192.168.0.50"})
js_insert("/admin/dhcps?form=reservation", {"mac": "...", "ip": "..."})
js_remove("/admin/nat?form=vs", {"key": "WireGuard"})
js_update("/admin/dhcps?form=reservation", {"key": "...", "ip": "..."})
```
---
## 🏗️ 架构
三种后端,混合:
```
┌───────────────────────────────────────────────────────────────────┐
│ MCP 客户端(Claude Code、Cursor 等) │
└──────────────────────────────────┬───────────────────────────────┘
│ stdio
▼
┌───────────────────────────────────────────────────────────────────┐
│ tplink-archer-mcp(FastMCP 服务器) │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────────────┐ │
│ │ 直接 │ ┌──────────────┐ ┌────────────────────────────┐ │
│ │ (库) │ │ Playwright │ │ JS-direct ★ 主要 │ │
│ │ ~100ms │ │ ~1-3s │ │ ~500ms │ │
│ │ 17 工具 │ │ 50 工具 │ │ 50 工具 │ │
│ └─────┬───────┘ └──────┬───────┘ └─────────────┬──────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ tplinkrouterc6u 无头 Chromium ──── store.read/write/... │
│ (身份验证 + 加密) (Vue UI 会话) │
└──────────────────────────────────┬───────────────────────────────┘
│ AES-CBC + HMAC-SHA256 over HTTP
▼
┌──────────────────────┐
│ TP-Link Archer AX53 │
│ (您的路由器) │
└──────────────────────┘
```
### 为什么有三种后端?
1. **直接(库)** 最快但有限 - 适用于 AX53 固件接受的 ~10 个端点。
2. **Playwright UI** 驱动表单点击;这是旧方法。选择器很脆弱。
3. **JS-direct** 动态导入路由器自己的 JS 模块并调用其 store 方法 - 两全其美:全覆盖,无脆弱选择器。
混合方法让您为每个调用选择速度与覆盖范围。新增工具默认为 JS-direct。
### 关键注意事项(从经验中学习)
1. **写入必须是部分差异**,而不是完整的配置。读取配置并写回整个对象会失败,错误代码为 `errorCode: server`。因为某些字段(`macaddr`、`extinfo`、`wps_state`)是只读/计算的。仅发送要更改的字段。
2. **字段名称与预期不符。** DHCP 保留使用 `mac` 和 `ip`,而不是 `macaddr`/`ipaddr`。始终先读取以了解模式。
3. **端点路径分为重启:**
- `/admin/reboot?form=set` - 调度重启配置
- `/admin/system?form=reboot` - 立即重启(带有 `operation: "reboot"`)
4. **一些端点使用 `load` 而不是 `read`** - 例如 DHCP 保留:`store.load("/admin/dhcps?form=reservation")`.
5. **块哈希随固件更新而更改。`JsBackend._discover_update_store_url()` 在启动时通过解析 index.html 发现它。
---
## 📚 发现 / 扩展
如果您的固件公开了我们尚未封装的端点:
```bash
# 走过 UI,捕获每个 API 调用
uv run python scripts/discover_endpoints.py
# → src/tplink_archer_mcp/endpoints_catalog.json
# 深入探测 - 捕获解密的响应
uv run python scripts/deep_probe2.py
# → scripts/deep_probe_v2_results.json
# 捕获 wire 体用于逆向工程
uv run python scripts/capture_request_bodies.py
# → scripts/captured_request_bodies.json
```
然后调用 `js_read("/admin/yourArea?form=yourForm")` 从 MCP 并检查结果。添加类型化包装器 `tools_js.py`。
---
## 📂 项目布局
```
src/tplink_archer_mcp/
├── server.py # FastMCP 入点
├── auth.py # 库身份验证包装器
├── config.py # 钥匙串 + 环境变量解析
├── serialize.py # JSON 帮助程序
├── playwright_backend.py # 无头浏览器会话 + JSON.parse 钩子
├── js_backend.py # ★ 动态导入 → store.read/write
├── tools_playwright.py # 24 读取工具(旧)
├── tools_playwright_write.py # 26 写工具(旧)
├── tools_js.py # ★ 50 个读+写工具(主要)
├── endpoints_catalog.json # 来自 UI 遍历的 40 个表单
├── endpoints_from_js.json # 317 个表单 + 81 个操作来自 JS 源
└── full_endpoint_map.json # 63 个已验证的读写 JS 端点
scripts/
├── discover_endpoints.py # Playwright UI 遍历器
├── deep_probe2.py # JSON.parse 钩子深度发现
├── capture_request_bodies.py # XHR 拦截用于协议 RE
├── test_writes_safe.py # 3 工具往返测试
├── test_all_js_tools.py # 全面的 js_* 工具测试
└── router-js/ # 403 个转储的 JS 文件(4 MB)用于分析
SESSION_REPORT.md # 详细的构建日志
LICENSE # MIT
README.md # 本文件
```
---
## 🧪 测试
包含的测试套件使用往返模式(读 → 翻转 → 验证 → 恢复 → 验证),因此即使测试失败,路由器状态始终恢复到起始状态:
```bash
uv run python scripts/test_all_js_tools.py
```
输出:
```
阶段 A:读取所有 js_get_* 工具
✓ js_get_wan_status 键=['lan_ipv4_dhcp_enable', 'lan_macaddr', ...]
✓ js_get_pppoe_config 键=['static_ip', 'access', 'mtu', ...]
... (24 more)
阶段 B: 往返测试写入工具
✓ js_set_alg(ftp) (flip) from_to=True→False
✓ js_set_alg(ftp) (restore) restored_to=True
... (more)
摘要: 37 pass / 3 fail / 1 manual fix
```
---
## 💡 实际应用
- **网络监控**: “告诉我当新设备加入我的网络时”(使用 cron 驱动的 Claude 会话)
- **带宽分配**: “限制我兄弟的 PC 到 10 Mbps”(结合 `pw_set_dhcp_reservation` + QoS)
- **安全审计**: “显示当前从 WAN 端口打开的所有内容”(端口转发 + DMZ + UPnP 服务)
- **备份配置**: 每周读取所有设置并转储为 JSON 进行版本控制备份
- **智能家居自动化**: “在凌晨 2 点禁用 IoT WiFi,早上 7 点重新启用”(通过调度的 MCP 调用)
- **故障排除**: “为什么我的笔记本无法连接?” → 检查 DHCP 租约、访问控制、IP-MAC 绑定
---
## 🤝 贡献
拉取请求欢迎。添加新的路由器型号支持:
1. 首先使用 `js_*` 工具测试 - 它们很可能直接生效
2. 运行 `scripts/discover_endpoints.py` 测试您的路由器
3. 将新的 `endpoints_catalog.json` 与 `full_endpoint_map.json` 进行比较 - 标记差异
4. 在 `tools_js.py` 中为您的路由器特有的端点添加类型化工具
5. 更新上面的 **支持的路由器** 表
6. 打开一个 PR
用于协议逆向工程,请参阅 `SESSION_REPORT.md` 以了解用于破解 AX53 的方法。
---
## ⚖️ 许可
[MIT](LICENSE) - 您想怎么处理就怎么处理。感谢您提供署名,但不是必需的。
---
## 🙏 鸣谢
- **[`tplinkrouterc6u`](https://github.com/AlexandrErohin/TP-Link-Archer-C6U)** 由 Alexandr Erohin - 原始的 Python 库处理身份验证 + 加密。直接后端包装此库。
- **[`tplink-archer-ax53-guide`](https://github.com/Mahir-Isikli/tplink-archer-ax53-guide)** - 全面的 AX53 设置指南,提示了 JS API 方法。
- **[FastMCP](https://github.com/jlowin/fastmcp)** - MCP 服务器框架。
- **[Playwright](https://playwright.dev/)** - 用于无头浏览器会话驱动程序。
由 [@sharozdawa](https://github.com/sharozdawa) 构建 - 灵感来自一次太多次点击路由器管理页面。
---
## 🌟 给这个仓库点个星星
如果它为您节省了时间或让您微笑,请给它点个星星。并告诉正在运行 TP-Link 路由器的其他人 - 他们可能也需要这个。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器