关于 tolpo
tolpo 是面向家庭网络中 AI Agent 和代码的 TP-Link Tapo 设备本地控制接口,直接通过局域网通信。它按级别限制敏感或难以撤销的操作。
主要功能
- 01基于局域网的设备发现与控制
- 02设备状态和传感器读数
- 03灯、插座、摄像头等设备支持
- 04可配置的操作安全级别
- 05MCP 服务和 OpenAPI HTTP API
适用场景
- 01查看门窗、温度和告警
- 02调节灯光或切换插座
- 03获取已配置摄像头的快照
- 04为脚本开放智能家居设备控制
MCP 相关
MCP 服务将 Tapo 设备状态和获准的控制操作作为工具提供给 AI 客户端。同一核心还提供带 OpenAPI 描述的 HTTP API。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
以本地优先的方式,为 AI Agent 控制 TP-Link Tapo 智能家居设备。
tolpo 将网络中的 Tapo 设备整合为一个统一接口,供 AI Agent 或你自己的代码读取和控制。它通过开源库 python-kasa 在局域网内直接与每台设备通信,因此任何请求都不会离开你的家,也不会经过厂商云端。它唯一需要的凭据是设备已关联的 Tapo 账户。
它基于同一核心提供两种接口:
- MCP 服务,助手(例如 Claude)可将其用作工具(
turn off the office lights、“有门开着吗?”)。 - HTTP API,在
/docs提供 OpenAPI 描述,供脚本和仪表板使用。
目标是让 Agent 能够完成 Tapo 应用在你的网络上能做的一切:控制灯、插座、集线器及其传感器、摄像头、门铃、扫地机器人、日程安排、固件、房间、配对,甚至控制设备向互联网发送的内容。这赋予了 Agent 很多权限,因此每项操作都有一个级别,只有最低级别默认启用。请参阅Agent 能做什么和安全模型。
功能
- 支持灯、插座、H100/H200 集线器及其传感器、摄像头和门铃,每种设备都提供实时状态和可更改项目列表。
- Tapo 应用的各个部分会划分为不同区域,例如灯、插座、摄像头、门铃和网络。tolpo 会记住之前运行时发现的设备类型;你从未拥有过的类型所对应的区域会保持关闭。
- 每项操作都有 0 到 4 级。读取和可逆控制(电源、亮度、颜色)默认启用。设置、安全变更以及难以撤销的操作(例如配对或恢复出厂设置)默认关闭,需提升级别后才能使用;最后两类操作还需要每次调用时提供确认短语。Wi-Fi 名称、设置代码、密码和令牌绝不会返回。
- 在配置中指定摄像头名称后,Agent 即可通过 Tapo 应用使用的同一视频通道获取单张图片、一段短图片序列或已保存的视频片段。无需额外的摄像头账户。
- 设备发现结合广播和针对每个地址的直接扫描,会在运行之间记住设备,并重试唤醒较慢的设备。无法连接设备时,响应会说明具体设备和原因。
- 状态会短暂缓存,设备名称也能立即解析,因此 Agent 不会被响应缓慢的集线器阻塞。
- 完整测试套件使用模拟设备运行,无需任何硬件。
支持的设备
tolpo 适用于所有 python-kasa 能够连接的设备,因此列表范围比我们实际拥有的硬件更广。表格将两类设备区分开来:我们使用真实设备测试过的,以及 python-kasa 文档中标记为支持、但我们尚未尝试过的设备。
| 设备 | 在此处测试过 | python-kasa 文档中支持,但未在此处尝试 | Agent 可获取的信息 | |
|---|---|---|---|---|
| 彩色灯泡 | L430C | L430P、L530B、L530E、L530EA、L535E | 状态、亮度、白光色温和颜色 | |
| 智能插座 | P115 | P110、P110M | 状态,以及功率、电压和电流读数 | |
| 集线器 | H200 | H100,以及与集线器配对的 S200B 和 S200D 按钮 | 与其配对的传感器会作为独立设备显示,也可以读取其事件日志。使用更高权限级别时:警报器、传感器设置、配对 | |
| 门窗传感器 | T110 | 开启或关闭状态、电池电量低标记 | ||
| 温湿度传感器 | T310 | T315(带显示屏的型号) | 温度、湿度、电池电量低标记 | |
| 运动传感器 | T100 | 按照 python-kasa 文档提供的运动状态。未使用真实硬件验证 | ||
| 漏水传感器 | T300 | 漏水警报和电池电量 | ||
| 摄像头 | C225、C610、C465 | C100、C101、C110、C200、C210、C220、C325WB、C460、C520WS、C720、TC40、TC65、TC70 | 状态、电池电量(适用时)、最近一次警报和检测开关。使用更高权限级别时:检测调整、图像和音频设置、水平和垂直转动、存储卡。可启用的摄像头还能获取图片和视频片段 | |
| 门铃 | D230 | D100C、D130 | 状态和电池电量、通过集线器获取图片和实时视频。使用更高权限级别时:铃声、快捷回复、防盗、唤醒 | |
| 扫地机器人 | python-kasa 清洁模块支持的型号 | 状态、启动和停止、房间和区域、吸力和水量、计划任务。根据应用的协议构建,未使用真实硬件验证 | ||
| 门锁 | python-kasa 不支持 | 暂不可用。DL100、DL105、DL110、DL130 和 DLW10 使用的协议不受 python-kasa 识别。tolpo 可以解析它们的发现记录,但尚未连接任何功能 |
C610 和 C465 尚未列入 python-kasa 的设备清单,但两者都能正常连接。C465 需要在 compat.py 中进行一处小型证书修复。完整的上游设备列表见 python-kasa 的 SUPPORTED.md。
未列出的型号也可能可用,因为 tolpo 会将设备交给 python-kasa 处理,并显示其报告的内容。运行 tolpo scan 即可确认。无论设备能否正常工作,都请通过设备支持问题告知我们,以便完善此表。
环境要求
- Python 3.11 或更高版本
- 同一网络上的一个或多个 TP-Link Tapo 设备,并已在 Tapo 应用中完成设置
- Tapo 账户邮箱和密码
- ffmpeg,仅在需要获取摄像头图片时需要
- 用于安装的 uv(或普通的
pip)
安装
使用 npx
npx -y tolpo scan # find your devices
npx -y tolpo mcp # run as an MCP server
tolpo 是一个 Python 程序。npm 包中包含 Python 代码,并通过 uv 运行,因此首次运行会下载大约 40 个 Python 包,耗时比之后的运行更长。如果 AI 客户端不再等待,请先运行一次 npx -y tolpo --help,然后重新启动客户端。
使用 Docker
适用于长期运行的设备,例如 Raspberry Pi 或 Linux 家庭服务器。镜像是公开的,因此拉取时无需登录,并且支持 amd64 和 arm64。
将凭据保存在只有你能读取的文件中,并通过 --env-file 传入:
(umask 077; printf '[email protected]\nTAPO_PASSWORD=your-password\n' > ~/.tolpo.env)
docker run --rm -i --network host --env-file ~/.tolpo.env ghcr.io/signerless/tolpo
这会通过 stdio 运行 MCP 服务。对于 HTTP API,请添加令牌,因为它不再绑定到 loopback:
echo "TOLPO_TOKEN=$(openssl rand -hex 24)" >> ~/.tolpo.env
docker run -d --name tolpo --restart unless-stopped --network host --env-file ~/.tolpo.env \
ghcr.io/signerless/tolpo serve --host 0.0.0.0
--network host 可让容器通过 UDP 广播发现设备,但仅适用于 Linux。macOS 和 Windows 上的 Docker Desktop 会在虚拟机中运行容器,无法以这种方式发现设备,因此请在这些系统上使用 npx 安装方式。
CI 会为两种架构构建镜像,并在镜像内检查 MCP 握手。目前尚未尝试从容器内发现真实设备。镜像不包含 ffmpeg,因此目前无法获取摄像头图片。
从源代码安装
git clone https://github.com/signerless/tolpo && cd tolpo
uv venv --python 3.13 .venv
uv pip install --python .venv/bin/python -e ".[dev]"
配置
凭据可以来自环境变量或配置文件。服务会先读取文件,然后由环境变量覆盖其中的设置。
export TAPO_EMAIL='[email protected]'
export TAPO_PASSWORD='your-password'
也可以使用 ~/.config/tolpo/config.toml(其中包含密码,请对其运行 chmod 600):
[tapo]
email = "[email protected]"
password = "your-password"
# or point at an existing JSON file instead of copying the secret:
# credentials_file = "~/.tapo_config.json"
[server]
host = "127.0.0.1" # loopback only; a token is required to bind elsewhere
port = 8765
# token = "a-long-random-string"
# cache_ttl_seconds = 10
# areas = ["lights", "plugs", "hub"] # which parts offer tools; empty means every part for the devices you own
[discovery]
# subnets = ["192.168.1.0/24"] # default: the /24 of your default-route interface
# hosts = ["192.168.10.20"] # devices that ignore broadcast or live on another VLAN
# sweep = true # also probe every address in the subnet (networks up to /22)
interval_seconds = 600
[policy]
# The highest level of action an agent may use, from 0 to 4. See the Security model.
tier = 1
# Single device methods an agent may use above `tier`, for example ["setLedStatus"].
allow_methods = []
# Features an agent may write beyond power, brightness and color.
# Plain ids ("pan_left") or kind-qualified ones ("camera.state").
allow_write = []
[cameras]
# Pictures are off for every camera until you name it here, as it is called in the Tapo app.
snapshots = [] # for example ["Hallway Cam"]
# Optional. A camera account made in the Tapo app switches pictures to the standard RTSP stream.
# username = "camera-account-name"
# password = "camera-account-password"
# ffmpeg = "/opt/homebrew/bin/ffmpeg" # only if ffmpeg is not on your PATH
# clip_dir = "/Users/you/tolpo-clips" # the one folder where camera clips may be saved; no folder, no clips
环境变量会覆盖文件中的设置:TOLPO_CONFIG(配置文件本身)、TOLPO_CREDENTIALS_FILE、TOLPO_TIER、TOLPO_AREAS(以逗号分隔的名称)、TOLPO_SNAPSHOTS、TOLPO_CLIP_DIR、TOLPO_FFMPEG、TOLPO_CAMERA_USERNAME 和 TOLPO_CAMERA_PASSWORD。如果 tier 不是 0 到 4 之间的整数,服务将无法启动。
部分功能使用独立文件,以免任何机密信息进入主配置文件。自动化功能会保存其规则和警报发件箱;本地房间和分组保存在 ~/.local/state/tolpo 中(可通过 TOLPO_STATE_DIR 更改)。网络区域会读取 ~/.config/tolpo/network.toml(可通过 TOLPO_NETWORK_CONFIG 更改),该文件指定每个路由器密码所在的环境变量,但不会保存密码本身。
通过只读扫描验证设置:运行 npx -y tolpo scan,或在源代码检出目录中运行 .venv/bin/tolpo scan。
与 Claude(MCP)搭配使用
将凭据放入 ~/.config/tolpo/config.toml(请参阅 Configuration,并对其运行 chmod 600)。服务会自行读取该文件,因此不会将任何机密信息写入 AI 客户端的设置。然后注册一次服务:
claude mcp add tolpo -- npx -y tolpo mcp
如果使用源代码检出,请指向你自己的副本:
claude mcp add tolpo -- $PWD/.venv/bin/tolpo mcp
如果你不想将凭据保存在文件中,也可以通过 -e TAPO_EMAIL=... -e TAPO_PASSWORD=... 传递,但客户端会以纯文本形式将它们存储在自己的设置中。
下次重启后,你可以提出诸如“将 office-1 调暗至 30%”、“有没有门开着?”或“楼上的温度是多少?”之类的问题。
| 工具 | 功能 |
|---|---|
home_overview | 一览全屋情况:哪些设备已开启、门窗是否打开、水警报、离线设备、低电量电池、温度 |
list_devices | 查看设备及其状态;可按 kind 或名称筛选 |
get_device | 查看单个设备的所有功能,以及哪些功能可写入 |
camera_snapshot | 获取一台已启用摄像头的静态图片 |
set_power | 控制灯和插座的开关;接受多个目标和 office* 之类的通配符 |
set_light | 设置亮度、白光色温或色相与饱和度 |
set_feature | 设置其他功能,但仅限策略允许的情况 |
rescan | 查找新设备或已移动的设备 |
读取工具标记为只读,set_feature 标记为破坏性操作,因此 MCP 客户端可在必要时请求确认。响应内容精简:典型家庭的所有设备信息不到一千个 token。
Agent 可以做什么
Tapo 应用分为多个区域。每个区域是一组 MCP 工具,拥有自己的页面,其中列出该区域的所有工具。tolpo 会记住先前运行时发现的设备类型,并关闭从未拥有过的设备类型对应的区域,因此没有扫地机器人的家庭不会加载扫地机器人工具。首次运行或模型无法识别时,所有区域都会开启。可通过 [server] 下的 areas 或 TOLPO_AREAS 自行选择区域。工具 tolpo_areas 会告知 Agent 当前开启的区域。
| 区域 | 涵盖内容 | 工具数 |
|---|---|---|
| 灯 | 灯泡和灯带:效果、预设、计划、倒计时、离家模式、通电默认设置 | 19 |
| 插座 | 插座和开关:计划、倒计时、能耗历史、电价、自动关闭、保护 | 21 |
| 集线器 | 集线器、传感器和散热器阀门:警报器、传感器设置、门、漏水、移动和按钮事件日志 | 29 |
| 门铃 | 可视门铃和门铃扬声器:铃声、快捷回复、防盗、唤醒、电池模式 | 17 |
| 摄像头检测 | 移动、人、宠物和车辆检测、区域、计划、警报和聚光灯、警报通知设置 | 17 |
| 摄像头系统 | 云台转动、图像、音频、电池、隐私模式、UPnP、固件、重启 | 33 |
| 摄像头媒体 | 存储卡、录制计划、录制索引、过往事件的缩略图、保存到文件夹的片段 | 11 |
| 吸尘器 | 扫地机器人:状态、启动和停止、房间和区域、吸力和水量、计划、磨损计数器 | 27 |
| 门锁 | 门锁:从发现记录中读取状态。目前尚不可用 | 1 |
| 设备管理 | 名称、时钟、LED、固件,以及 tolpo 自己的房间和分组 | 24 |
| 自动化 | 替代 Smart Actions 的本地规则引擎:触发条件、条件、操作和警报发件箱 | 10 |
| 配对 | 配对和移除集线器设备、连接 Wi-Fi、重启和恢复出厂设置。大部分操作需要等级 4,重启需要等级 2 | 9 |
| 家庭平面图 | 3D 视图的平面图:根据设备绘制草图、读取、保存,以及查看位置 | 4 |
| 历史记录 | 门或窗开启的频率和持续时间,数据来自 tolpo record 保存的内容 | 1 |
| 网络 | 通过路由器、DNS 服务器或防火墙查看每台设备与哪些对象通信,并可选择阻止通信。阻止通信需要等级 4、在 network.toml 中设置 mode = "enforce",且 Linux 主机需负责路由流量 | 10 |
此外,home_overview、list_devices、get_device、set_power、set_light、set_feature、
camera_snapshot 和 rescan 适用于所有设备。
所有区域合计有 242 个工具。它们的名称、描述和参数列表约占 40,000 个令牌。标准设置只会启用与家中检测到的设备相匹配的区域。一次性加载所有工具的客户端可以使用 areas 仅保留所需工具。
其中大部分内容基于对 Tapo 应用的分析构建,并在模拟设备上进行了测试。每个区域页面都会说明哪些部分在真实设备上试用过,哪些没有。对于请求的确切格式基于推测的情况,页面会标记为 UNVERIFIED;如果设备未报告支持该格式,工具就会拒绝执行。
通过 HTTP 使用
npx -y tolpo serve # or .venv/bin/tolpo serve from a source checkout
# http://127.0.0.1:8765, interactive docs at /docs
# Read
curl -s localhost:8765/devices # everything, with state and capabilities
curl -s localhost:8765/devices/front-door # one device, every feature
curl -s "localhost:8765/devices?kind=sensor" # doors, windows, water, temperature
# Write
curl -s localhost:8765/devices/hallway-cam/snapshot -o picture.jpg # a camera you enabled
curl -s -X POST localhost:8765/devices/desk-lamp/power \
-H 'content-type: application/json' -d '{"on": true}'
curl -s -X POST localhost:8765/devices/office-1/light \
-H 'content-type: application/json' -d '{"brightness": 40, "color_temp": 3000}'
curl -s -X POST localhost:8765/batch/light \
-H 'content-type: application/json' -d '{"targets": ["office*"], "brightness": 60}'
可以通过设备的简短 id(office-1)、其在 Tapo 应用中的名称(不区分大小写)来指定设备;在批量端点中,还可以使用 office* 这样的 glob 模式。如果某个名称匹配多台设备,服务会返回 409 并列出候选设备,而不会猜测。
3D 房屋视图
tolpo serve 还会在 http://127.0.0.1:8765/home 提供房屋的 3D 视图。它会绘制各个房间,将每台
设备放在所属房间,并显示设备状态:灯光会呈现实际颜色,墙上的门或窗在传感器报告打开时会开启,漏水会变红,温度会显示在传感器上方。点击设备即可切换开关、调节亮度或更改颜色。点击摄像头或门铃即可观看实时画面。没有设备的房间不会显示。
户型图由你决定,并保存在你的设备上,路径为 ~/.config/tolpo/home.json(可通过 server.home_layout 或
TOLPO_HOME_LAYOUT 更改)。最简单的创建方式是让你的 Agent“绘制我的户型图”:使用 home_plan_draft、home_plan_get 和 home_plan_set 工具,它会根据你的设备拟定户型图,询问房间信息并保存。你也可以在视图中点击 Edit layout,将设备拖到对应位置,然后保存。格式说明见 docs/areas/home_plan.md:
{"version": 1,
"rooms": [{"id": "office", "name": "Office", "x": -7, "z": -5, "w": 5, "d": 5},
{"id": "garden", "name": "Garden", "x": -9, "z": -12, "w": 21, "d": 7, "outside": true}],
"devices": {"office-1": {"room": "office", "x": -5.75, "z": -3.75},
"garden-cam": {"room": "garden", "x": 1.5, "z": -5.6, "yaw": 0}}}
实时视频来自 GET /devices/{id}/live,这是摄像头的 JPEG 图片流(每秒约 10 张),摄像头需列在 cameras.snapshots 中。每台摄像头只能开启一个视频流,最多同时使用两台摄像头。视频会在 15 分钟后结束;如果是电池供电的摄像头,则会在 2 分钟后结束,因为实时视频会让它保持唤醒。页面会从一个固定版本的 jsDelivr 路径加载 three.js,且只会与此服务通信。页面每 5 分钟查询一次电池摄像头的状态,而不是每隔几秒查询一次,因此不会唤醒它们。
门窗历史记录
对于连接到 TP-Link 云的传感器,Tapo hub 不会自行保存历史记录:按应用的方式查询时,H200 对门传感器会返回空列表,而应用会改为从云端读取历史记录。因此,tolpo 会自行记录:
tolpo record garage
它每 5 秒读取一次传感器状态(可通过 --every 更改),并将每次开关状态及时间保存到 ~/.local/share/tolpo/history.jsonl(可通过 server.history_file 或 TOLPO_HISTORY_FILE 指定);只有你能读取此文件。不指定名称即可记录所有门窗传感器。它只会在运行期间记录,因此要想获得没有缺漏的历史记录,请将其作为后台服务运行;电脑休眠或传感器无法连接的时段会记录为间隔。之后,recorded_history 工具会告诉 Agent 门每天开启了多少次、每次持续多久,并按天和小时统计;如果有时段没有记录,也会列出,而不是对此进行猜测。
相机照片
Agent 可以向相机请求一张静态照片。除非在配置中通过 Tapo 应用里的名称指定相机,否则所有相机均处于关闭状态:
[cameras]
snapshots = ["Hallway Cam"]
运行 tolpo 的机器上还需要安装 ffmpeg。请在 Agent 使用前自行检查设置。这会将一张照片保存到只有你能读取的文件中:
npx -y tolpo snapshot "Hallway Cam" -o hallway.jpg
若要在自己的屏幕上实时观看相机画面,请使用 npx -y tolpo watch "Hallway Cam"。它会打开 ffplay(ffmpeg 附带的程序),并在你关闭窗口时退出。添加 --seconds 30 可让它更早停止。不会录制任何内容,也不会向 Agent 发送任何内容。
tolpo 使用 ffmpeg 从相机的实时视频流中截取一帧,并以 JPEG 格式返回,宽度最多为 1280 像素。--quality high 会请求主码流,而不是小码流。连接视频流有两种方式:
- 使用 Tapo 应用的视频通道,连接相机的 8800 端口。它使用 tolpo 已有的 Tapo 账户,因此无需进行其他设置。
- 使用 RTSP:在 Tapo 应用中创建相机账户,并在
[cameras]下添加username和password。配置了相机账户后,tolpo 会使用 RTSP。
启用前请注意:
- 照片会发送给 Agent 使用的大模型。仅启用你愿意让它查看的相机。
- 相机处于隐私模式时不会提供照片。除非在
allow_write中允许camera.state,否则 Agent 无法关闭隐私模式。 - 每张照片都会记录相机和时间,但不会记录照片本身。
- 如果相机拒绝登录,tolpo 会让它静置五分钟,因为反复登录失败可能会导致相机被锁定。
- 照片是实时截取的一帧,不是录像。电池供电的相机可能处于休眠状态,无法响应。
- 使用 RTSP 时,ffmpeg 会在命令行中接收相机账户信息,因此同一台机器上的其他用户可能会在短时间内看到这些信息。
- 连接到集线器的门铃没有自己的地址。它的照片和实时视频会像在应用中一样通过集线器传输;电池供电的门铃唤醒时,获取第一张照片大约需要 5 s。目前还无法访问它的录像。
camera_media 区域基于此功能提供更多能力。它可以读取存储卡及其录像索引、返回过往事件的缩略图、从实时视频流中连续截取一小段时间的照片,并将录像保存到你指定的唯一文件夹 clip_dir。缩略图、连续截取的照片和录像遵循与照片相同的规则:只能使用你指定的相机,且相机不能处于隐私模式;保存录像的工具只会返回路径,不会返回视频。读取存储卡状态、录像计划以及录像和事件列表适用于任何相机。格式化存储卡属于 4 级操作。
安全模型
此服务会控制实体设备,因此默认拒绝操作,只有在你提出请求时才会放宽限制。
设备上的每项操作都有一个级别。你可以在 [policy] 下使用 tier 选择 Agent 可使用的最高级别(默认为 1),也可以通过 allow_methods 单独允许高于该级别的设备方法。
| 级别 | 名称 | 含义 | 示例 |
|---|---|---|---|
| 0 | 读取 | 查看所有非机密内容 | 状态、设置、能耗、事件日志、存储卡索引 |
| 1 | 控制 | 可逆操作,就像你手动操作一样 | 电源、亮度、颜色、摄像头转动、启动和停止吸尘器 |
| 2 | 设置 | 更改设备行为 | 计划、检测调节、默认值、重命名、自动化规则 |
| 3 | 安全 | 涉及安全或隐私 | 摄像头隐私模式、警笛、报警和布防状态、关闭摄像头补光灯、UPnP、音频输出 |
| 4 | 生命周期 | 难以撤销的操作 | 配对和移除设备、恢复出厂设置、安装固件、更改 Wi-Fi、更改防火墙、格式化存储卡 |
级别 3 和 4 的每次调用还需要确认短语,例如 setLedStatus hallway-cam。拒绝信息会说明需要使用的短语,因此该短语的作用是暂停操作,让 Agent 询问用户,而不是证明用户已同意。短语会指出操作和设备(少数短语会指定一项更改或计划),因此同一个确认不能用于另一台设备或另一项操作。拒绝信息会说明操作内容,但绝不会说明如何放宽权限。
| 范围 | 允许的操作 |
|---|---|
| 读取 | 所有非机密内容。绝不会返回 Wi-Fi 名称、设置代码、密码、令牌、密钥和 MAC 地址 |
| 控制 | 级别 1 下控制灯和插座的电源、亮度、色温、颜色和灯光预设 |
| 更多 | tier 所允许的任何级别,或 allow_methods 中指定的单个方法 |
| 功能 | 通过 set_feature 写入的其他内容,须在 policy.allow_write 中指定(报警测试、水平/垂直转动、检测开关) |
| 图片 | 仅限 cameras.snapshots 中指定的摄像头。默认关闭。其他摄像头工具(设置、存储卡索引、事件列表)在你允许的级别下适用于所有摄像头 |
| 配对 | 仅通过配对工具进行,级别为 4。set_feature 中的集线器 pair 和 unpair 功能仍会被阻止 |
通过 set_feature 操作摄像头时只允许读取:摄像头上的 state 开关是隐私快门,而不是电源继电器,因此不会被视为电源继电器。请通过 allow_write = ["camera.state"] 明确启用它,或使用级别 3 的隐私工具。在任何级别下,allow_write 中指定的功能都会被允许,且不需要确认短语,因此只应指定你确实愿意开放的功能。
无人请求时自动运行的规则(自动化)也受相同级别限制,并在运行时检查,而不只是在创建时检查。设置自动化规则需要级别 2。Agent 可随时停止所有规则,但重新启动规则需要级别 3 和确认短语。你也可以自行运行 tolpo automation resume;已在运行的服务会在重启时应用此命令。
此服务仅监听 127.0.0.1。如果使用其他地址且未提供 bearer 令牌,服务会拒绝启动;未提供令牌时,它还会拒绝 Host 标头不是本地地址的请求,从而阻止网页发起 DNS 重绑定攻击。
设备名称是由设置设备的人自由输入的文本。服务会对名称进行扁平化和缩短处理,再提供给 Agent;发送给 Agent 的指令也会要求其将名称和读数视为数据,而不是命令。共享的 Tapo 账户意味着账户中的任何人都可以重命名设备,因此请仅与信任的人共享账户。
忙碌网络中的发现机制
家庭中通常有许多设备,其中一些依靠电池供电,响应较慢。发现机制专为此类情况设计:
- 先进行 UDP 广播,再向子网中的每个地址直接查询(
discovery.sweep), 因为有些电池供电的摄像头会忽略广播,却总能响应直接查询。 - 以前发现过的设备会记录在
~/.cache/tolpo/hosts.json中(地址、名称和型号, 不含机密信息),并在启动时直接查询。某台设备在某次扫描中未出现,不会因此被遗忘; 30 天未出现的条目会被删除。 - 对于没有响应的设备,会在 5、15 和 45 秒后重试,并在每次重新扫描时再次尝试。
启动过程分阶段进行,让服务立即可用:首次扫描在后台运行,每台设备一旦响应便立即连接。只要设备已上线,就可以立即使用你指定了确切名称的设备,无需等待集线器;集线器冷启动可能需要约 10 秒。涉及整个家庭的操作会等待扫描完成,但最长不超过 15 秒;仍在连接中的设备会在后台完成连接。
无法访问设备时,响应会明确说明。home_overview 和 list_devices 会包含 complete: false,以及 not_connected 列表,其中列出每台无法访问设备的名称、型号和原因,避免 Agent 将离线的门传感器误判为门已关闭。
面向 AI Agent
请先调用 tolpo_areas。它会列出 tolpo 中已启用的部分、各部分提供的功能,以及所有者允许的权限级别。如果你是受命配置或使用 tolpo 的 AI Agent,请从
llms.txt 开始。如果你受命修改代码,
请先阅读 AGENTS.md。
开发
.venv/bin/python -m pytest # runs against simulated devices, no hardware required
项目结构:
src/tolpo/
registry.py device discovery, state cache, control operations
policy.py what may be read and written (deny-by-default)
views.py shared presentation for the HTTP and MCP layers
api.py FastAPI HTTP server
mcp_server.py MCP server (stdio)
config.py config file and environment loading
compat.py small fixes for devices python-kasa cannot reach yet
snapshot.py one picture from a camera, taken with ffmpeg
media.py the video channel of the Tapo app (port 8800)
tsvideo.py finds the video track in a camera's stream
calls.py the one way an area sends a method to a device, checked against its level
provision.py Wi-Fi setup of a new device from this machine (SoftAP), behind a plan
areas/ one file per area of the Tapo app; adding an area adds a file
automation/ the local rule engine
network/ providers for routers, DNS servers and firewalls
cli.py serve / mcp / scan / snapshot / watch / automation entry points
tests/ full suite against simulated devices
docs/protocols.md how Tapo devices talk on the local network
docs/areas/ one page per area, with every tool and what was only tried with simulated devices
assets/ logo, device icons and social preview
请参阅 CONTRIBUTING.md 了解基本准则,参阅 docs/protocols.md 了解协议说明,并参阅 SECURITY.md 报告漏洞。
背景
Tapo 设备所使用的协议并未由供应商公开文档。本项目的一部分工作是独立分析官方 Tapo 应用和真实设备,以便软件能够与所有者已有的硬件互通。分析结果记录在 docs/protocols.md 中:各型号使用的传输方式、发现机制的工作原理、较新的 TPAP 协议的形式,以及我们无法确定的内容。说明均以我们自己的语言撰写,不含供应商代码、密钥或凭据;tolpo 本身也只会使用你自己的 Tapo 账户登录。
兼容性和状态
这是 0.2.1 版本。通过 python-kasa,支持使用 KLAP 和 SSL-AES 传输协议的灯、插座、集线器和传感器;此外,还为带有 ECDSA 证书的摄像头(例如 C465)提供了一个小型补丁(compat.py),以支持 python-kasa 无法独立访问的设备。
首个版本之后新增的部分,是通过分析 Tapo 应用构建的,并在模拟设备上进行了测试。曾在一处有 4 个灯泡、1 个集线器、8 个传感器、1 个门铃、3 个摄像头和 1 个插座的真实家庭环境中尝试读取数据。还在那里尝试了少数可还原的写入操作:灯泡(电源、亮度、颜色、开机默认值、已保存的预设和已禁用的规则)、插座(电源、倒计时、LED、开机默认值和已禁用的规则)、摄像头补光灯、集线器指示灯、麦克风音量、检测开关和自动化规则,之后均恢复了原状。大多数其他写入操作尚未在真实硬件上尝试,各部分页面会注明具体情况。机器人吸尘器、门锁、暖气片阀门和防火墙提供商均未在真实设备上尝试过。
已知限制:摄像头可提供静态图片、短时连续图片和已保存的片段,但无法向 Agent 提供连续视频;连接在集线器后的门铃可提供图片,但无法提供录像;应用中仅限云端的部分(账户、家庭、共享、推送通知、Tapo Care、语音助手)无法访问,自动化部分会在本地取代其中一些功能;MCP 服务通过 stdio 运行,每个客户端对应一个进程,目前尚无共享 HTTP 传输;HTTP API 包含原有路由,以及少数用于摄像头存储卡(/devices/{id}/storage、/recordings/...)和门锁状态的路由,其他部分则仅提供 MCP 工具;此外,尚未测试位于第二个子网中的设备。
许可证
MIT,详见 LICENSE。
本项目与 TP-Link 无关,也未获得其认可。Tapo 是 TP-Link 的商标。所有设备通信均通过开源 python-kasa 库进行。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。