“打开客厅的灯”——TRADFRI的一款真正能听到声音的MCP
   
宜家TRADFRI智能家居网关的MCP服务器。因为显然与瑞典灯泡交谈的唯一方法是通过DTLS上的CoAP,所以这个项目将所有仪式都打包到MCP工具中,这样AI助手就可以用简单的英语控制你的灯、插头和场景。不需要物联网协议的博士学位(尽管它肯定有助于写这篇文章)。
完整教程(又称战争日记):docs/openclaw-tradfri-mcp-tutorial.mdmacOS上的DTLS陷阱(即“为什么什么都不起作用”):docs/dtls-tradfri-pitfalls.md
______________________________________________________________________
这整件事是如何联系在一起的
User (Telegram / Web UI)
-> AI Agent (OpenClaw / Claude Desktop / etc.)
-> mcporter CLI (MCP client)
-> tradfri-mcp (Docker, FastMCP HTTP server, port 8765)
-> aiocoap (CoAP over DTLS)
-> TRADFRI gateway (LAN, UDP 5684)
-> Zigbee -> Lights / Plugs它实际的作用
- 自然语言控制 --“打开客厅的灯”很有效,每次都感觉很神奇
- 12个MCP工具 --开/关、亮度、色温、颜色、场景、状态以及可能需要的更多信息
- Alias系统 --将友好名称映射到设备、组或虚拟房间,因为没有人想记住设备ID 65553
- CoAP观察推送通知 --当灯光变化时,您会通过Telegram收到通知(例如通过遥控器或Apple Home),这样您就可以感觉到自己的房子在监视您
- Docker就绪 --
docker compose up -d像一个负责任的成年人一样,进行原木轮换 - TinyDTLS供应商 --为macOS打补丁;不依赖OpenSSL 3,因为这条路只会让人流泪
什么住在哪里
kc_tradfri_mcp/
├── server.py # FastMCP HTTP server (main entry)
├── coap_client.py # aiocoap wrapper (CoAP GET/PUT, singleton context)
├── config.py # Environment variable config
├── devices.py # Device topology (devices.json / aliases.json)
├── aliases.json # Custom aliases (incl. virtual rooms)
├── .tradfri_psk.json # PSK credentials (.gitignore)
├── .env / .env.example # Environment variables
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml / uv.lock
├── vendor/dtlssocket/ # DTLSSocket 0.2.3 (TinyDTLS patched for macOS)
├── scripts/
│ ├── gen_psk.py # Generate PSK credentials
│ └── scan.py # Scan gateway devices
├── openclaw-skill/ # OpenClaw skill (see "OpenClaw Integration")
│ ├── SKILL.md
│ ├── _meta.json
│ ├── .clawhub/origin.json
│ └── scripts/
│ └── tradfri # Wrapper script (simplifies mcporter calls)
└── docs/
├── dtls-tradfri-pitfalls.md
└── openclaw-tradfri-mcp-tutorial.md______________________________________________________________________
安全通知: 该项目专为受信任的家庭局域网环境而设计。MCP服务器未实现身份验证或TLS。在没有额外安全措施的情况下,不要将服务端口暴露给公共互联网。
快速入门(乐观版)
1.克隆并安装依赖项
git clone https://github.com/KerberosClaw/kc_tradfri_mcp.git
cd kc_tradfri_mcp
uv sync2.生成PSK证书
export TRADFRI_GATEWAY_IP=192.168.x.x
export TRADFRI_SECURITY_CODE=xxxxxxxxxxxxxxxx # printed on the gateway
uv run python scripts/gen_psk.py
# -> .tradfri_psk.json created如果您已经有了,请跳过此步骤.tradfri_psk.json. 有关DTLS问题,请参阅docs/dtls-tradfri-pitfalls.md你可能需要它。
3.扫描设备
uv run python scripts/scan.py
# Output saved to devices.json; or use mcporter call tradfri.refresh_devices later4.配置(简单部分,仅此一次)
cp .env.example .env
# Edit .env — set TRADFRI_GATEWAY_IP编辑 aliases.json 定义友好名称。支持四种类型,因为一种类型太简单了:
{
"Living Room": {
"type": "virtual",
"groups": [131079],
"devices": [65545, 65553, 65554, 65555]
},
"Bedroom": {"type": "group", "id": 131089},
"Dining Track": {"type": "device_list", "ids": [65579, 65580, 65581]},
"Desk Lamp": {"type": "device", "id": 65551}
}| 类型 | 描述 |
|---|---|
virtual | 虚拟房间:组合多个宜家集团+独立设备 |
group | 本土宜家集团 |
device_list | 设备集合(当不存在宜家集团时) |
device | 单台设备 |
5.启动它(Docker)
docker compose up -d
docker compose logs -f # verify DTLS handshake succeeds6.连接mcporter
npm install -g mcporter
mcporter config add tradfri --url http://localhost:8765/mcp
mcporter list tradfri # verify tools appear7.关键时刻
mcporter call tradfri.list_aliases
mcporter call tradfri.control_by_name name="Living Room" state=false
mcporter call tradfri.control_by_name name="Living Room" state=true
mcporter call tradfri.set_color_temp name="Desk Lamp" direction=warm______________________________________________________________________
MCP工具(您的新遥控器)
| 工具 | 说明 |
|---|---|
control_group | 控制一组(开/关、亮度) |
control_device | 控制单个设备 |
control_by_name | 最常用 --按别名控制(所有别名类型) |
set_color_temp | 调整色温(direction: warm/cool 或 mireds: 250-454) |
set_color | 设置颜色(RGB灯泡:红/绿/蓝/橙/黄/紫/粉) |
activate_scene | 触发一个场景 |
get_status | 查询实时状态(支持 name=) |
list_devices | 列出所有设备、组、场景和别名 |
list_aliases | 列出别名(轻量级,用于LLM快速查找) |
refresh_devices | 重新扫描网关,更新devices.json |
find_by_name | 将名称解析为ID |
send_notification | 电报推送通知(未配置时无提示) |
______________________________________________________________________
CoAP OBSERVE(又名你的房子自己纹身)
启动时,服务器在每个别名上订阅CoAP OBSERVE。当一盏灯改变状态时,比如有人使用物理遥控器或Apple Home,服务器会捕捉到它并发出Telegram通知。是的,当你的伴侣打开浴室灯时,你现在会收到一个推送通知。你已经被警告了。
要求: 集 TELEGRAM_BOT_TOKEN 和 TELEGRAM_CHAT_ID 在 .env.
它的行为方式:
- 在启动时捕获基线状态
- 仅在以下情况下通知 状态变化 (谢天谢地,不是初始值)
- OBSERVER订阅失败时自动重新连接(重试间隔:
TRADFRI_POLL_INTERVAL,默认30秒) - 不会干扰控制操作(OBSERVER拥有CoAP上下文生命周期,我们很难理解为什么这很重要)
______________________________________________________________________
环境变量
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
TRADFRI_GATEWAY_IP | 是 | -- | 网关局域网IP |
MCP_PORT | 8765 | HTTP服务器端口 | |
MCP_HOST | 0.0.0.0 | 绑定地址 | |
PSK_FILE | .tradfri_psk.json | PSK证书路径 | |
DEVICES_FILE | devices.json | 设备缓存路径 | |
ALIASES_FILE | aliases.json | 别名映射路径 | |
TELEGRAM_BOT_TOKEN | -- | Telegram Bot令牌(可选,用于推送通知) | |
TELEGRAM_CHAT_ID | -- | 电报聊天ID(可选) | |
TRADFRI_POLL_INTERVAL | 30 | 观察重新连接间隔(秒) |
Docker日志轮换(因为日志像杂草一样生长)
容器日志自动旋转(max-size: 10m,3个文件,30MB上限)。记录所有MCP工具调用(例如。 control_by_name(name='Living Room', state=True))用于无限制增长的调试。你未来的自己会感谢你的。
______________________________________________________________________
OpenClaw集成(有趣之处)
运作原理
OpenClaw没有 mcpServers config(与Claude Desktop不同,那不是很好吗)。其MCP集成使用 麦克波特技能:AI代理调用 mcporter CLI通过 exec 工具。
问题是:对于较小的LLM,复杂的mcporter语法就像巧克力茶壶一样可靠:
# Too complex for smaller models — multiple key=value params + different tool names
mcporter call tradfri.control_by_name name=Living\ Room state=true
mcporter call tradfri.set_color_temp name=Living\ Room direction=warm解决方案是 包装器脚本 它隐藏了所有粗糙的部分:
tradfri Living\ Room on
tradfri Living\ Room off
tradfri Living\ Room brightness 80 # percentage 0-100
tradfri Living\ Room colortemp warm
tradfri Desk\ Lamp color red # RGB bulbs: red/green/blue/orange/yellow/purple/pink
tradfri status Living\ Room
tradfri list安装
先决条件: mcporter已安装并配置(请参阅快速入门步骤6)。
1.安装OpenClaw技能
# Copy to OpenClaw workspace (symlinks not supported — OpenClaw rejects cross-directory realPath)
cp -r openclaw-skill ~/.openclaw/workspace/skills/tradfri2.安装包装脚本
ln -s $(pwd)/openclaw-skill/scripts/tradfri /opt/homebrew/bin/tradfri
# Linux: ln -s $(pwd)/openclaw-skill/scripts/tradfri /usr/local/bin/tradfri3.向AGENTS.md添加说明
添加 ~/.openclaw/workspace/AGENTS.md (不 系统提示, 不 SKILL.md--相信我):
## IKEA TRADFRI Light Control
When asked to control lights -> exec `tradfri` command immediately, no explanation needed.
tradfri Living\ Room on
tradfri Living\ Room off
tradfri Living\ Room brightness 80
tradfri Desk\ Lamp colortemp warm
tradfri Desk\ Lamp color red
tradfri status Desk\ Lamp
tradfri list重要提示: 只有AGENTS.md内容被完全注入LLM上下文。systemPrompt和SKILL.md没有可靠地包含在内。通过艰难的方式学会了这一点。
4.重新启动OpenClaw网关
launchctl kickstart -k gui/$(id -u)/ai.openclaw.gateway5.测试
通过Telegram告诉OpenClaw:“打开客厅的灯”,沐浴在成功的光芒中(字面意思)。
______________________________________________________________________
陷阱(所以你不必)
码头工人 network_mode: host 不适用于macOS
macOS Docker在LinuxKit虚拟机中运行。 network_mode: host 只暴露虚拟机的网络,而不是Mac的局域网。这是在Linux上完美运行的东西之一,然后在macOS上嘲笑你。
解决方案: 使用默认网桥网络+ ports 地图。网桥网络可以通过VM NAT到达LAN IP(包括网关UDP 5684)。适用于macOS和Linux。无聊,但正确。
# docker-compose.yml
services:
tradfri-mcp:
ports:
- "8765:8765" # do NOT use network_mode: hostCoAP上下文所有权:OBSERVER拥有重置权
最初 coap_put / coap_get 将在失败时重置CoAP上下文(_ctx = None).听起来很合理,对吧?除了它会破坏活动的OBSERVE会话,因为TRADFRI网关只允许每个PSK标识有一个DTLS会话。哎呀。
正确的方法(经过艰苦的学习):
coap_put/coap_get失败时: 不重置上下文,只是提高- OBSERVE任务检测到断开连接,然后调用
reset_ctx()清除陈旧的上下文 - 下一步
get_ctx()自动创建新的DTLS会话
OBSERVE不需要信号量序列化
我试过了 asyncio.Semaphore(1) +2秒延迟以序列化OBSERVER init,认为20个并发GET将使网关不堪重负。骄傲出现在秋天之前——测试证明网关可以很好地处理并发的OBSERVE GET。根本原因是上面的上下文重置错误,而不是并发性。
删除信号量将OBSERVER初始化时间从~40s缩短到几秒钟。有时,最好的优化是删除自己聪明的代码。
OpenClaw技能不能使用符号链接
如果 ~/.openclaw/workspace/skills/tradfri 是一个符号链接,OpenClaw拒绝它: Skipping skill path that resolves outside its configured root. 必须使用 cp -r不是我选择去死的那座山。
只有AGENTS.md被完全注入LLM上下文
openclaw.jsons systemPrompt 附加在系统提示的末尾,很容易截断。 SKILL.md 只引用了名称/描述,没有内容。仅 AGENTS.md 内容完全显示在LLM的系统提示中。在弄清楚之前,我花了令人尴尬的时间调试它。
_comment 在aliases.json中崩溃list_devices
A. "_comment": "..." 字符串输入 aliases.json 原因 target.get("type") 坠毁。修复:跳过非字典条目。这种bug需要2秒修复,2小时才能找到。
______________________________________________________________________
故障排除(“为什么它不起作用”部分)
| 错误 | 解决方案 |
|---|---|
CredentialsMissingError | 删除 :5684 从凭据URI--请参阅 dtls-tradfri-pitfalls.md #9 |
| DTLS握手失败 | TinyDTLS C源代码需要修补——请参阅 dtls-tradfri-pitfalls.md #6 #7 |
NetworkError 循环 | 确保 coap_client.pys coap_put/coap_get 不要设置 _ctx = None (见上文陷阱) |
| 未找到设备 | mcporter call tradfri.refresh_devices 或 uv run python scripts/scan.py |
| mcporter无法连接 | docker compose ps 为了验证容器, curl http://localhost:8765/mcp 验证HTTP |
| Docker容器无法访问网关 | macOS不支持 network_mode: host;使用桥+ ports (见上文陷阱) |
______________________________________________________________________
开发(没有Docker的危险生活)
TRADFRI_GATEWAY_IP=192.168.x.x uv run python server.py
# MCP Inspector (Web UI)
npx @modelcontextprotocol/inspector http://localhost:8765/mcp
# -> http://localhost:6274______________________________________________________________________
相关项目(更多我建造的东西)
- kc_openclaw_cal_llm --开放式法律+本地法学硕士:实际可行的方法
- kc_ai_技能 --实际做事的AI技能
