tolpo について
tolpo は、家庭内ネットワークで動作する AI エージェントやコード向けの TP-Link Tapo デバイス制御インターフェースです。LAN 経由で直接通信し、段階的な権限レベルで機微な操作や取り消しにくい変更を制限します。
主な機能
- 01LAN 経由のデバイス検出と制御
- 02状態とセンサー値の取得
- 03照明、プラグ、カメラなどに対応
- 04設定可能な操作の安全レベル
- 05MCP サーバーと OpenAPI HTTP API
活用シーン
- 01ドア、窓、温度、アラートを確認
- 02照明を調整したりプラグを切り替え
- 03設定済みカメラのスナップショットを取得
- 04スクリプトにスマートホーム制御を提供
MCP 対応
MCP サーバーは Tapo デバイスの状態と許可された操作をツールとして AI クライアントに公開します。同じコアから OpenAPI 定義付きの HTTP API も利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
AI エージェント向けの、ローカル優先型 TP-Link Tapo スマートホームデバイス制御。
tolpo は、ネットワーク上の Tapo デバイスを、AI エージェントや独自コードから読み取り、制御できる単一のインターフェースにまとめます。オープンソースの python-kasa ライブラリを通じて LAN 経由で各デバイスと直接通信するため、リクエストが自宅の外に出ることはなく、ベンダーのクラウドを経由することもありません。必要な認証情報は、デバイスがすでに登録されている Tapo アカウントだけです。
同じコア上で、次の 2 つのインターフェースを提供します。
- Claude などのアシスタントがツールとして使う MCP サーバー(「オフィスの照明を消して」「開いているドアはある?」)。
- スクリプトやダッシュボード向けの HTTP API。
/docsに OpenAPI の説明があります。
目指しているのは、ネットワーク上で Tapo アプリからできることを、すべてエージェントでも実行できるようにすることです。照明、プラグ、ハブとそのセンサー、カメラ、ドアベル、ロボット掃除機、スケジュール、ファームウェア、部屋、ペアリング、さらにはデバイスがインターネットに送信する内容まで扱えます。強力な機能が多いため、すべての操作にレベルがあり、最初は最初のレベルだけが有効です。詳しくは、エージェントができることとセキュリティモデルをご覧ください。
機能
- 照明、プラグ、H100/H200 ハブとそのセンサー、カメラ、ドアベルに対応し、それぞれライブ状態と変更可能な項目の一覧を確認できます。
- Tapo アプリの機能は、照明、プラグ、カメラ、ドアベル、ネットワークなどの領域に分けられています。tolpo は、以前の実行時に検出したデバイスの種類を記憶し、これまで所有したことのない種類の領域は無効のままにします。
- すべての操作には 0〜4 のレベルがあります。読み取りと元に戻せる制御(電源、明るさ、色)は有効です。設定、セキュリティの変更、ペアリングや工場出荷時設定へのリセットなど元に戻しにくい操作は、レベルを上げるまで無効です。また、最後の 2 種類の操作では、呼び出しごとに確認フレーズも必要です。Wi-Fi 名、セットアップコード、パスワード、トークンが返されることはありません。
- 設定で名前を指定したカメラは、Tapo アプリと同じ映像チャンネルを通じて、静止画、短い連続画像、または保存済みクリップをエージェントに提供します。追加のカメラアカウントは必要ありません。
- デバイスの検出では、ブロードキャストとアドレスごとの直接スキャンを組み合わせます。デバイスを実行間で記憶し、起動が遅いデバイスには再試行します。デバイスに接続できない場合は、対象のデバイスと理由を応答で知らせます。
- 状態は短時間キャッシュされ、デバイス名もすぐに解決されるため、エージェントが応答の遅いハブを待たされることはありません。
- シミュレーションデバイスを使った完全なテストスイートを実行できるため、ハードウェアは必要ありません。
対応デバイス
tolpo は python-kasa が通信できるデバイスであれば動作するため、一覧には所有しているハードウェアより多くの機種が含まれています。この表では、実機で動作確認したものと、python-kasa が対応を明記しているものの、こちらでは試していないものを分けています。
| デバイス | こちらで動作確認済み | python-kasa では対応と記載、こちらでは未確認 | エージェントが利用できる機能 | |
|---|---|---|---|---|
| カラーバルブ | 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 に渡し、python-kasa が報告する内容をそのまま表示するためです。tolpo scan を実行して確認してください。デバイスが動作した場合も、動作しなかった場合も、デバイス対応に関するissueでお知らせください。表の改善に役立ちます。
要件
- Python 3.11 以降
- 同じネットワーク上にある Tapo アプリでセットアップ済みの TP-Link Tapo デバイスが 1 台以上
- Tapo アカウントのメールアドレスとパスワード
- カメラの画像が必要な場合のみ、ffmpeg
- インストール用の uv(または通常の
pip)
インストール
npx を使用する場合
Node と uv が必要です。グローバルには何もインストールされません。
npx -y tolpo scan # find your devices
npx -y tolpo mcp # run as an MCP server
tolpo は Python プログラムです。npm パッケージに Python コードが含まれており、uv を使って実行されます。そのため、初回実行時は約 40 個の Python パッケージがダウンロードされ、2 回目以降より時間がかかります。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
これにより、MCP サーバーが stdio 経由で起動します。HTTP API を使用する場合は、ループバックにバインドされなくなるため、トークンを追加してください。
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% に暗くして」「開いているドアはある?」「2 階の温度は?」などと尋ねることができます。
| ツール | 機能 |
|---|---|
home_overview | 家全体の状況をひと目で確認できます。電源が入っているもの、開いているドアや窓、水漏れの警告、オフラインのデバイス、電池残量の低下、温度などを表示します |
list_devices | 状態を含むデバイスの一覧です。kind または名前で絞り込めます |
get_device | 1 台のデバイスのすべての機能と、書き込み可能な機能を確認できます |
camera_snapshot | 有効にしたカメラの静止画を 1 枚取得します |
set_power | ライトやプラグを切り替えます。複数の対象や office* のようなワイルドカードを指定できます |
set_light | 明るさ、白色温度、色相と彩度を設定します |
set_feature | ポリシーで許可されている場合に限り、その他の機能を設定します |
rescan | 新しいデバイスや移動したデバイスを探します |
読み取りツールは読み取り専用、set_feature は破壊的操作としてマークされているため、必要に応じて MCP クライアントから確認を求めることができます。応答は簡潔で、一般的な住宅の全デバイスの情報が 1,000 トークン未満に収まります。
エージェントでできること
Tapo アプリは複数のエリアに分かれています。各エリアは MCP ツールのグループで、それぞれのページにすべてのツールが一覧表示されます。tolpo は以前の実行で見つかったデバイスの種類を記憶します。これまで所有したことのない種類のエリアはオフになるため、掃除機のない家では掃除機用ツールは読み込まれません。初回の実行時やモデルが認識されない場合は、すべてのエリアがオンになります。[server] の下にある areas または TOLPO_AREAS で、エリアを自分で選択してください。tolpo_areas ツールを使うと、エージェントはオンになっているエリアを確認できます。
| 分野 | 内容 | ツール数 |
|---|---|---|
| lights | 電球とライトストリップ:エフェクト、プリセット、スケジュール、カウントダウン、おでかけモード、電源投入時のデフォルト設定 | 19 |
| plugs | プラグとスイッチ:スケジュール、カウントダウン、エネルギー履歴、電気料金、自動オフ、保護機能 | 21 |
| hub | ハブ、センサー、ラジエーターバルブ:サイレン、センサー設定、ドア、漏水、動作、ボタンのイベントログ | 29 |
| doorbell | ビデオドアベルとチャイム:呼び出し音、クイック返信、盗難防止、起動、バッテリーモード | 17 |
| camera_detection | 動体、人、ペット、車両の検出、ゾーン、スケジュール、アラームとスポットライト、警告の対象 | 17 |
| camera_system | パン・チルト、画像、音声、バッテリー、プライバシーモード、UPnP、ファームウェア、再起動 | 33 |
| camera_media | メモリーカード、録画プラン、録画インデックス、過去のイベントのサムネイル、フォルダーに保存されたクリップ | 11 |
| vacuum | ロボット掃除機:ステータス、開始と停止、部屋とゾーン、吸引力と水量、スケジュール、消耗度カウンター | 27 |
| lock | ドアロック:ディスカバリーレコードから状態を読み取ります。現時点では使用できません | 1 |
| device_admin | 名前、時計、LED、ファームウェア、tolpo 独自の部屋とグループ | 24 |
| automation | Smart Actions に代わるローカルルールエンジン:トリガー、条件、アクション、アラート送信ボックス | 10 |
| pairing | ハブデバイスのペアリングと削除、Wi-Fi への接続、再起動、工場出荷時設定へのリセット。大半の操作にはレベル 4 が必要で、再起動にはレベル 2 が必要です | 9 |
| home_plan | 3D ビューの間取り図:デバイスから下書きを作成し、読み込み、保存する方法と、表示場所 | 4 |
| history | ドアや窓が開いた回数と時間。tolpo record で保存されたデータに基づきます | 1 |
| network | ルーター、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 を設定します)。最も簡単な方法は、エージェントに「家の間取りを作成して」と頼むことです。エージェントは
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 から取得します。これは cameras.snapshots に登録したカメラから、JPEG 画像をストリーミングします(毎秒約 10 枚)。カメラごとにストリームは 1 つで、同時に使用できるカメラは 2 台です。ビューは 15 分後、またはバッテリー駆動カメラでは 2 分後に終了します。ライブ映像を使うとカメラが起動状態のままになるためです。このページは固定された 1 つの jsDelivr パスから three.js を読み込み、このサーバーとのみ通信します。バッテリー駆動カメラの状態確認は数秒ごとではなく、5 分ごとに行うため、カメラを起動させません。
ドアと窓の履歴
Tapo ハブは、TP-Link のクラウドに接続されたセンサーの履歴を独自には保存しません。アプリと同じ方法で要求すると、H200 はドアセンサーについて空のリストを返し、アプリは代わりにクラウドから履歴を読み込みます。そのため、tolpo は独自に履歴を記録します。
tolpo record garage
センサーを 5 秒ごとに読み取り(変更するには --every を指定)、開閉のたびに時刻とともに ~/.local/share/tolpo/history.jsonl に保存します(保存先は server.history_file または TOLPO_HISTORY_FILE で変更できます)。このファイルを読めるのは自分だけです。名前を指定しない場合は、すべてのドアセンサーと窓センサーを記録します。記録されるのは tolpo の実行中のみなので、履歴に欠落がないようバックグラウンドサービスとして実行してください。コンピューターがスリープしていた時間やセンサーに接続できなかった時間は、欠落として記録されます。recorded_history ツールは、ドアが開いた頻度や開いていた時間を日別・時間別にエージェントに伝え、記録がない時間も推測せずに一覧表示します。
カメラの画像
エージェントはカメラに静止画を1枚リクエストできます。設定で、Tapo アプリに表示されている名前を指定するまで、すべてのカメラはオフです。
[cameras]
snapshots = ["Hallway Cam"]
また、tolpo を実行するマシンに ffmpeg が必要です。エージェントが使用する前に、ご自身でセットアップを確認してください。これにより、ご自身だけが読み取れるファイルに画像が1枚保存されます。
npx -y tolpo snapshot "Hallway Cam" -o hallway.jpg
ご自身の画面でカメラのライブ映像を見るには、npx -y tolpo watch "Hallway Cam" を使います。ffmpeg に付属する ffplay が起動し、ウィンドウを閉じると終了します。--seconds 30 を指定すると、より早く停止します。録画は行われず、エージェントにも何も送信されません。
tolpo は ffmpeg でカメラのライブストリームから1フレームを取得し、最大幅1280ピクセルの JPEG として返します。--quality high を指定すると、小さいストリームではなくメインストリームを使用します。ストリームに接続する方法は2つあります。
- Tapo アプリのビデオチャンネルを、カメラのポート8800で使用します。tolpo がすでに持っている Tapo アカウントを使用するため、追加の設定は必要ありません。
- Tapo アプリでカメラアカウントを作成し、
[cameras]の下にusernameとpasswordとして追加すると、RTSP を使用できます。カメラアカウントが設定されている場合、tolpo は RTSP を使用します。
有効にする前に知っておくべきこと:
- 画像は、エージェントが実行する AI モデルに送信されます。見せてもよいカメラだけを有効にしてください。
- プライバシーモード中のカメラからは画像を取得できません。
allow_writeでcamera.stateを許可しない限り、エージェントがプライバシーモードをオフにすることはできません。 - すべての画像について、カメラ名と時刻がログに記録されます。画像自体は記録されません。
- カメラがログインを拒否した場合、tolpo は5分間そのカメラへの接続を試みません。失敗が繰り返されると、カメラがロックアウトされる可能性があるためです。
- 画像は現在の1フレームであり、録画ではありません。バッテリー式カメラはスリープ中の場合があり、応答しないことがあります。
- RTSP を使う場合、ffmpeg はカメラアカウントをコマンドライン引数として受け取るため、同じマシン上の他のユーザーに一時的に見える可能性があります。
- ハブに接続されたドアベルには、個別のアドレスがありません。画像とライブ映像はアプリと同様にハブ経由で取得され、バッテリー式ドアベルが起動するため、最初の画像の取得には約5秒かかります。録画にはまだアクセスできません。
camera_media エリアは、これらの機能を拡張します。メモリーカードと録画インデックスの読み取り、過去のイベントのサムネイルの取得、ライブストリームからの短い連続画像の取得、そして clip_dir に指定した1つのフォルダーへの録画の保存ができます。サムネイル、連続画像、クリップには、画像と同じルールが適用されます。指定したカメラのみが対象で、プライバシーモード中のカメラは対象外です。また、クリップを保存するツールが返すのはパスだけで、動画は返しません。カードの状態、録画計画、録画とイベントの一覧の読み取りは、どのカメラでも利用できます。カードのフォーマットはレベル4の操作です。
セキュリティモデル
このサーバーは物理的な機器を制御するため、デフォルトでは拒否し、要求があった場合にのみ許可範囲を広げます。
デバイスに対する各操作にはレベルがあります。[policy] の tier(デフォルトは 1)でエージェントが使用できる最高レベルを選び、allow_methods でそれを超える個別のデバイスメソッドを許可できます。
| レベル | 名前 | 内容 | 例 |
|---|---|---|---|
| 0 | 読み取り | 秘密ではないあらゆる情報の確認 | 状態、設定、エネルギー、イベントログ、メモリーカードのインデックス |
| 1 | 制御 | 手動操作と同様に元に戻せる操作 | 電源、明るさ、色、カメラの旋回、掃除機の開始と停止 |
| 2 | 設定 | 動作を変更する操作 | スケジュール、検出の調整、デフォルト、名前の変更、自動化ルール |
| 3 | セキュリティ | 安全性やプライバシーに関わる操作 | カメラのプライバシーモード、サイレン、アラームと警戒状態、カメラライトの消灯、UPnP、音声出力 |
| 4 | ライフサイクル | 元に戻すのが難しい操作 | デバイスのペアリングと削除、工場出荷時設定へのリセット、ファームウェアのインストール、Wi-Fi の変更、ファイアウォールの変更、メモリーカードのフォーマット |
レベル 3 と 4 では、setLedStatus hallway-cam のような確認フレーズも呼び出しごとに必要です。拒否メッセージにはフレーズが示されます。つまり、このフレーズはエージェントがユーザーに確認を求めるための一時停止であり、ユーザーが同意した証明ではありません。このフレーズは操作とデバイスを指定します(変更内容や計画を指定するものも一部あります)。そのため、ある確認を別のデバイスや操作に再利用することはできません。拒否メッセージには操作内容が示されますが、許可範囲を広げる方法は示されません。
| 範囲 | 許可される内容 |
|---|---|
| 読み取り | 秘密ではないすべての情報。Wi-Fi 名、セットアップコード、パスワード、トークン、キー、MAC アドレスは返されません |
| 制御 | レベル 1 での照明とプラグの電源、明るさ、色温度、色、ライトプリセット |
| その他 | tier で許可したレベルの操作、または allow_methods で指定した個別のメソッド |
| 機能 | その他の set_feature による書き込み。policy.allow_write で指定します(アラームテスト、パン/チルト、検出スイッチなど) |
| 画像 | cameras.snapshots で指定したカメラのみ。デフォルトではオフです。その他のカメラツール(設定、カードのインデックス、イベント一覧)は、許可したレベルであればすべてのカメラで使用できます |
| ペアリング | レベル 4 のペアリングツール経由のみ。ハブの pair および unpair 機能は set_feature で引き続きブロックされます |
カメラでは set_feature による書き込みは読み取り専用です。カメラの state スイッチは電源リレーではなくプライバシーシャッターであるため、電源リレーとしては扱われません。allow_write = ["camera.state"] で意図的に有効にするか、レベル 3 のプライバシーツールを使用してください。allow_write で指定した機能はどのレベルでも許可され、確認フレーズも必要ありません。そのため、許可する機能だけを指定してください。
ユーザーから要求されずに実行されるルール(自動化)にも、設定時だけでなく実行時に同じレベルが適用されます。ルールの設定にはレベル 2 が必要です。エージェントはいつでもすべてのルールを停止できますが、再開にはレベル 3 と確認フレーズが必要です。自分で再開するには tolpo automation resume を実行してください。すでに実行中のサーバーは、再起動時にこの操作を反映します。
サーバーがリッスンするのは 127.0.0.1 のみです。ベアラートークンなしで別のアドレスを指定すると起動を拒否します。また、トークンがない場合は Host ヘッダーがローカルではないリクエストも拒否し、ウェブページからの DNS リバインディング攻撃を防ぎます。
デバイス名は、デバイスをセットアップした人が入力する自由形式のテキストです。サーバーはエージェントに表示する前に名前を平坦化して短縮し、送信する指示では、名前や測定値をコマンドではなくデータとして扱うようエージェントに伝えます。Tapo アカウントを共有している場合、アカウント内の誰もがデバイス名を変更できます。そのため、アカウントは信頼できる人だけで共有してください。
ビジーネットワークでの検出の仕組み
家庭には多くのデバイスがあり、バッテリー駆動で応答が遅いものもあります。検出はそのような状況を考慮して設計されています。
- UDP ブロードキャストを送信した後、サブネット内の各アドレスに直接クエリを送信します(
discovery.sweep)。 バッテリー駆動のカメラの中にはブロードキャストを無視しても、直接問い合わせれば必ず応答するものがあるためです。 - 以前に検出したデバイスは
~/.cache/tolpo/hosts.json(アドレス、名前、モデル。シークレットは含みません)に記録され、起動時に直接クエリされます。1 回のスキャンで見つからなかったデバイスが忘れられることはありません。30 日間検出されていない項目は削除されます。 - 応答しないデバイスには 5 秒後、15 秒後、45 秒後に再試行し、スキャンのたびに再度試行します。
サーバーをすぐに利用できるよう、起動時の処理は段階的に行われます。最初のスキャンはバックグラウンドで実行され、各デバイスは応答した時点で接続されます。名前を正確に指定したデバイスは、起動すればすぐに利用でき、ハブを待つ必要はありません。ハブはコールドスタートから起動するのに約 10 秒かかる場合があります。家全体を対象とする操作はスキャンの完了を待ちますが、待機時間は 15 秒を超えません。接続中のデバイスが残っている場合は、バックグラウンドで接続を完了します。
到達できないデバイスがある場合は、その旨が応答に示されます。home_overview と list_devices には complete: false と、到達できないデバイスそれぞれの名前、モデル、理由を含む not_connected リストが付加されるため、エージェントがオフラインのドアセンサーを「ドアが閉まっている」と誤認することはありません。
AI エージェント向け
まず tolpo_areas を呼び出してください。これにより、tolpo のどの機能が有効になっているか、それぞれが何を提供するか、所有者が許可しているレベルがわかります。tolpo のセットアップまたは使用を依頼された AI エージェントは、まず
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 トランスポートに対応しています。また、python-kasa 単独では接続できない C465 などの ECDSA 証明書を使用するカメラ向けに、小規模なパッチ(compat.py)も用意しています。
最初のリリース以降の機能は、Tapo アプリを分析して実装し、シミュレートしたデバイスでテストしました。実際の家庭では、電球 4 台、ハブ 1 台、センサー 8 台、ドアベル 1 台、カメラ 3 台、プラグ 1 台を使って読み取りを試しました。元に戻せる書き込みもいくつか試しました。具体的には、電球(電源、明るさ、色、電源オン時のデフォルト、保存したプリセット、無効にしたルール)、プラグ(電源、カウントダウン、LED、電源オン時のデフォルト、無効にしたルール)、カメラのライト、ハブのライト、マイクの音量、検出スイッチ、自動化ルールをそれぞれ変更し、その後元に戻しました。それ以外の書き込みのほとんどは実機で試しておらず、その領域のページにその旨を記載しています。ロボット掃除機、ドアロック、ラジエーターバルブ、ファイアウォールプロバイダーは、実機では一度も試していません。
既知の制限事項:カメラでは静止画、短い連続画像、保存済みクリップを取得できますが、エージェント向けの連続動画には対応していません。また、ハブ経由のドアベルでは画像を取得できますが、録画は取得できません。アプリのクラウド専用機能(アカウント、ホーム、共有、プッシュ通知、Tapo Care、音声アシスタント)にはアクセスできませんが、自動化領域ではその一部をローカルで代替します。MCP サーバーは stdio を介して動作し、クライアントごとに 1 つのプロセスを起動します。共有 HTTP トランスポートにはまだ対応していません。HTTP API には元からあるルートに加え、カメラのメモリーカード(/devices/{id}/storage、/recordings/...)とドアロックの状態に関するルートがいくつかありますが、その他の領域は MCP ツールのみです。また、2 つ目のサブネット上のデバイスはテストしていません。
ライセンス
MIT ライセンスです。詳しくは LICENSE をご覧ください。
このプロジェクトは TP-Link と提携しておらず、同社からの承認も受けていません。Tapo は TP-Link の商標です。すべてのデバイス通信は、オープンソースの python-kasa ライブラリを通じて行われます。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。