mcpField
C
ccu-mcp

ccu-mcp

本地服务
github.com/claymore666其他92 天前更新

关于 ccu-mcp

ccu-mcp 将 HomeMatic CCU 接入 MCP 客户端,提供设备、房间、程序和系统变量的操作。它通过本地 JSON-RPC API 连接,可查询和控制智能家居设备。

主要功能

  1. 01浏览设备、房间和程序
  2. 02读取并设置设备数值
  3. 03查看系统变量
  4. 04发现设备并解析类型
  5. 05直接连接 CCU API

适用场景

  1. 01查看房间温度和窗户状态
  2. 02调整暖气设定温度
  3. 03查找电量不足的设备
  4. 04查看燃气表读数

MCP 相关

将 HomeMatic 设备、房间、程序和系统变量作为 MCP 工具提供。MCP 客户端可通过 stdio 运行它,也可连接独立的 HTTP 服务。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"claymore666-ccu": {
"command": "npx",
"args": [
"-y",
"ccu-mcp"
],
"env": {
"CCU_HOST": "<CCU_HOST>",
"CCU_PASSWORD": "<CCU_PASSWORD>",
"CCU_USER": "<CCU_USER>",
"CCU_HTTPS": "<CCU_HTTPS>",
"CCU_PORT": "<CCU_PORT>",
"CACHE_DIR": "<CACHE_DIR>",
"MCP_ALLOWED_ORIGINS": "<MCP_ALLOWED_ORIGINS>",
"MCP_ALLOWED_HOSTS": "<MCP_ALLOWED_HOSTS>",
"CCU_PROFILES": "<CCU_PROFILES>",
"CCU_DEFAULT_PROFILE": "<CCU_DEFAULT_PROFILE>",
"CCU_TLS_VERIFY": "<CCU_TLS_VERIFY>",
"CCU_TLS_FINGERPRINT": "<CCU_TLS_FINGERPRINT>",
"CCU_CA_CERT": "<CCU_CA_CERT>",
"CCU_TIMEOUT": "<CCU_TIMEOUT>",
"CCU_SCRIPT_TIMEOUT": "<CCU_SCRIPT_TIMEOUT>",
"CACHE_TTL": "<CACHE_TTL>",
"CCU_RATE_LIMIT_BURST": "<CCU_RATE_LIMIT_BURST>",
"CCU_RATE_LIMIT_RATE": "<CCU_RATE_LIMIT_RATE>",
"RESOURCE_POLL_INTERVAL": "<RESOURCE_POLL_INTERVAL>",
"LOG_LEVEL": "<LOG_LEVEL>"
}
}
}
}
启动命令npx -y ccu-mcp
需要配置的环境变量
CCU_HOSTHostname or IP of your HomeMatic CCU (debmatic, CCU3, or OpenCCU/RaspberryMatic)
CCU_PASSWORD密钥CCU admin password (same as the WebUI login). Must be set; the value may be empty for a CCU with no password
CCU_USERCCU username
CCU_HTTPSConnect to the CCU via HTTPS (self-signed certificates supported)
CCU_PORTCCU API port (80 for HTTP, 443 for HTTPS)
CACHE_DIRDirectory for the device type cache and session persistence
MCP_ALLOWED_ORIGINSComma-separated allowlist of browser origins. Unset = no cross-origin browser access (default-deny). An allowlisted origin is reflected exactly in Access-Control-Allow-Origin (never '*'); the list also drives DNS-rebinding origin checks
MCP_ALLOWED_HOSTSExtra Host header values accepted by DNS-rebinding protection (comma-separated host:port); add your hostname when behind a proxy or container DNS name
CCU_PROFILESComma-separated names of multiple CCU targets (e.g. 'prod,dev'). Each profile takes the flat CCU_* settings prefixed CCU_<NAME>_ (CCU_PROD_HOST, ...), plus policy flags CCU_<NAME>_PROTECTED (writes need confirm:true) and CCU_<NAME>_READONLY. Unset = single default profile from the flat CCU_* vars
CCU_DEFAULT_PROFILEWhich profile from CCU_PROFILES is active at startup (default: the first listed)
CCU_TLS_VERIFYVerify the CCU's TLS certificate against the system trust store. Only meaningful with CCU_HTTPS=true. Default false, because a CCU ships a self-signed certificate — prefer CCU_TLS_FINGERPRINT or CCU_CA_CERT to verify one of those
CCU_TLS_FINGERPRINTPin the CCU's self-signed leaf certificate by its SHA-256 fingerprint (hex, colons optional). The strongest option for an appliance: the connection is rejected unless the presented certificate matches. Takes precedence over CCU_CA_CERT
CCU_CA_CERTPath to a PEM file holding the CCU's CA or self-signed certificate. The connection is then validated against it with standard chain verification
CCU_TIMEOUTTimeout for a CCU JSON-RPC call, in MILLISECONDS
CCU_SCRIPT_TIMEOUTTimeout for HomeMatic Script execution (ReGa), in MILLISECONDS — scripts are slower than plain API calls
CACHE_TTLLifetime of the on-disk device-type schema cache, in SECONDS
CCU_RATE_LIMIT_BURSTToken-bucket burst size for CCU requests — how many may be issued back to back
CCU_RATE_LIMIT_RATESustained CCU request rate, in requests per second
RESOURCE_POLL_INTERVALHow often MCP resources are polled for change notifications, in SECONDS
LOG_LEVELerror | warn | info | debug. Logs are structured JSON on stderr

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmccu-mcp1.11.7

工具

28

收录的工具列表 · 更新于 3 天前

参数类型必填说明
namestring否按设备/通道名称筛选(子字符串,不区分大小写)
roomstring否按房间名称筛选(完全匹配)
typestring否按设备类型筛选(完全匹配,例如 'HmIP-eTRV-2')
targetstring否要从中读取的 CCU 目标(默认:当前活动目标)。请参阅 list_ccu_targets。
functionstring否按功能组名称筛选(完全匹配)

详细介绍

OpenSSF Best Practices OpenSSF Scorecard

ccu-mcp

通过 Claude、Cursor 或任何 MCP 客户端与你的 HomeMatic 智能家居对话。

ccu-mcp MCP 服务

ccu-mcp 连接到 CCU 内置的 JSON-RPC API,并将你的设备、房间、程序和系统变量作为 MCP 工具提供。无需附加组件,无需 XML-API,也无需云服务——只需直接连接到本地网络中的 CCU。

兼容任何 HomeMatic CCU:debmatic(运行于 Debian 上的 HomeMatic)、CCU3 或 OpenCCU(原 RaspberryMatic)——只要支持标准的 /api/homematic.cgi 端点即可。

它能做什么?

你可以向 AI 助手提出这样的问题:

  • “浴室的温度是多少?”
  • “有窗户开着吗?”
  • “把客厅暖气设为 21 度”
  • “显示所有电量低的设备”
  • “燃气表读数是多少?”
  • “哪些设备电量低,或者已经很久没有被发现?”
  • “找出所有名称与设备名称不匹配的通道”
  • “将所有设备重命名为统一的命名规范,并标注楼层(UG/OG/EG)”
  • “窗户传感器在哪个房间?”

MCP 服务负责设备发现、类型解析、会话管理和值转换——AI 只需调用工具。

前提条件

  • 网络中可访问且正在运行的 HomeMatic CCU(debmatic、CCU3 或 OpenCCU——原 RaspberryMatic)
  • CCU 管理员用户名和密码(与登录 WebUI 时使用的凭据相同)
  • Node.js 24+(用于从源代码运行或以 stdio 模式运行)或 Docker

快速开始

export CCU_HOST=your-ccu-hostname-or-ip
export CCU_PASSWORD=your-ccu-admin-password
npx ccu-mcp --stdio

如果它在 stderr 中输出 server_ready,就表示运行正常。按 Ctrl+C 停止。现在在你的 MCP 客户端中进行设置——请参见下文。

如果旁边出现 cache_save_failed … mkdir '/data',在这里可以忽略,但在实际使用中建议修复:CACHE_DIR 默认值为 /data(Docker 布局),因此在容器外部运行时,设备类型缓存和 CCU 会话不会在运行之间持久保存。将它指向一个可写位置: export CACHE_DIR="$HOME/.cache/ccu-mcp"(或在 .env / env 配置块中设置相同的键)。

希望获得引导式设置?npx ccu-mcp init 会探测你的 CCU、固定其 TLS 证书、测试登录、写入一个可直接使用的 .env 文件,并输出对应的 MCP 客户端配置——请参见命令行标志。

安装

有两种运行方式:stdio(服务作为 MCP 客户端的子进程运行)或 HTTP(服务在 Docker 中独立运行,客户端通过网络连接)。请选择一种。

选项 A:stdio(直接运行,最简单)

这是最简单的设置方式。你的 MCP 客户端(Claude Code、Cursor 等)会将服务作为子进程启动——无需 Docker、无需网络配置,也无需身份验证令牌。

对于 Claude Code,请在项目目录(或你会使用 Claude Code 的任何目录)中创建一个 .mcp.json 文件:

{
  "mcpServers": {
    "ccu-mcp": {
      "command": "npx",
      "args": ["ccu-mcp", "--stdio"],
      "env": {
        "CCU_HOST": "your-ccu-hostname-or-ip",
        "CCU_PASSWORD": "your-ccu-admin-password"
      }
    }
  }
}

将 your-ccu-hostname-or-ip 替换为你的 CCU 主机名(例如 homematic-ccu3)或 IP(例如 192.168.1.50),并将 your-ccu-admin-password 替换为你登录 CCU WebUI 时使用的密码。

重启 Claude Code。运行 /mcp 检查连接状态。你应该会在列表中看到 ccu-mcp。

或者,使用 Claude Code CLI:

claude mcp add ccu-mcp -- npx ccu-mcp --stdio
选项 B:Docker(独立 HTTP 服务)

如果你希望服务独立运行,例如运行在家用服务器上、供多个客户端访问,或者 MCP 客户端支持 HTTP 远程连接,请使用此选项。

1. 启动容器。 镜像已发布到 GHCR,支持 linux/amd64 和 linux/arm64(因此也可在 CCU 旁的 Raspberry Pi 上运行),在每种 架构上原生构建并经过证明——gh attestation verify oci://ghcr.io/claymore666/ccu-mcp:latest --repo claymore666/ccu-mcp 可证明该镜像来自此仓库的发布工作流。

docker pull ghcr.io/claymore666/ccu-mcp:latest

每次发布也会发布对应的 X.Y.Z 标签——如果你希望自行决定升级时机,可以固定使用该标签,而不是 latest。 如需从源代码构建:

git clone https://github.com/claymore666/ccu-mcp.git && cd ccu-mcp
docker build -t ghcr.io/claymore666/ccu-mcp .

然后运行:

docker run -d \
  --name ccu-mcp \
  -e CCU_HOST=your-ccu-hostname-or-ip \
  -e CCU_PASSWORD=your-ccu-admin-password \
  -e MCP_ALLOWED_HOSTS=your-server-ip:3000 \
  -v ccu-data:/data \
  -p 3000:3000 \
  ghcr.io/claymore666/ccu-mcp:latest

远程客户端必须设置 MCP_ALLOWED_HOSTS。 服务的 DNS 重绑定防护会拒绝任何 Host 标头不在允许列表中的请求——默认情况下,仅允许 MCP 端口上的 localhost/127.0.0.1/[::1]。请将客户端用于访问服务的所有名称/IP 添加到列表中(以逗号分隔,格式为 host:port)。如果未设置,本地健康检查可以正常运行, 但所有远程 MCP 请求都会收到 403 Invalid Host header。

2. 获取身份验证令牌。 服务首次启动时会生成一个随机的 bearer 令牌,并将其保存在容器的数据卷中。你需要使用此令牌对 MCP 客户端进行身份验证。使用以下命令获取:

docker exec ccu-mcp grep MCP_AUTH_TOKEN /data/.env

命令会输出类似 MCP_AUTH_TOKEN=e96suzi1iG0H-GPif6K2... 的内容。= 后面的部分就是你的令牌。

3. 配置 MCP 客户端。 如果客户端使用 .mcp.json,请添加 HTTP 服务:

{
  "mcpServers": {
    "ccu-mcp": {
      "url": "http://your-server-ip:3000",
      "headers": {
        "Authorization": "Bearer PASTE-YOUR-TOKEN-HERE"
      }
    }
  }
}

如需自动注入令牌(需要 jq):

TOKEN=$(docker exec ccu-mcp grep MCP_AUTH_TOKEN /data/.env | cut -d= -f2)
jq --arg t "$TOKEN" '.mcpServers["ccu-mcp"].headers.Authorization = "Bearer " + $t' .mcp.json > .mcp.json.tmp && mv .mcp.json.tmp .mcp.json

此操作只会更新 ccu-mcp 条目,不会更改 .mcp.json 中的其他服务。

4. 检查服务是否正常运行:

curl http://localhost:3000/health
基于浏览器的客户端(CORS)

默认情况下,HTTP 服务不会发送任何 CORS 标头,因此随机网页无法控制本地实例。如需让 MCP Inspector 等基于浏览器的 MCP 客户端直接连接,请将 MCP_ALLOWED_ORIGINS 设置为可信来源的逗号分隔允许列表(例如 https://app.example,http://localhost:6274)。对于 Origin 在列表中的请求,服务会将该来源的原值写入 Access-Control-Allow-Origin,绝不会使用通配符 *,因为那会让任何网站都能控制管理真实 CCU 硬件的本地实例。来自其他来源的请求不会获得 CORS 标头(浏览器会阻止该请求),并且会被服务端的 DNS 重绑定防护拒绝。无论如何都会强制执行身份验证:每个 MCP 请求都需要 bearer 令牌。

默认情况下,HTTP 传输也会启用 DNS 重绑定防护:它会拒绝 Host 标头不是配置端口上的 localhost/127.0.0.1/[::1] 的请求。如果你通过其他主机名或 IP 访问服务(反向代理、容器 DNS 名称、服务所在的局域网地址),请将这些主机添加到 MCP_ALLOWED_HOSTS,否则合法请求会收到 403。

TLS。 bearer 令牌会随请求传输,因此除回环地址以外的连接都应加密。你有两种选择:在前置反向代理(Caddy/nginx)处终止 TLS,并将服务绑定到回环地址(MCP_HOST=127.0.0.1);或者设置 MCP_TLS_CERT 和 MCP_TLS_KEY 为 PEM 证书/密钥对,由服务自行提供 HTTPS。仍然完全支持普通 HTTP,并且它依旧是零配置默认选项;但如果服务通过非回环地址绑定并以未加密的 HTTP 传输令牌,启动时会记录警告。设置 MCP_ALLOW_PLAINTEXT=true 即表示确认知悉这一点,并可关闭该警告。

令牌轮换与过期。 默认情况下,bearer 令牌永不过期。你可以组合使用两项可选控制措施,在不让客户端断开连接的情况下轮换令牌:

  • 自动生成的令牌 — 设置 MCP_AUTH_TOKEN_TTL_DAYS(允许小数天)为生成的令牌指定有效期。服务会在令牌即将过期前在运行时自动轮换(无需重启;如果服务停机期间令牌已过期,也会在启动时轮换),并将新令牌打印到 stderr,同时让刚被替换的令牌在 MCP_AUTH_TOKEN_GRACE_HOURS 指定的时长内(默认为 24 小时)仍可通过验证,以便正在进行请求的客户端平稳切换。若要提前轮换,请删除 $CACHE_DIR/.env(或只删除其中的 MCP_AUTH_TOKEN 行)并重启。
  • 显式设置的令牌 — 如果你自行设置 MCP_AUTH_TOKEN,令牌有效期由你负责(TTL 不适用)。若要轮换,请将新令牌写入 MCP_AUTH_TOKEN,将旧令牌移至 MCP_AUTH_TOKEN_PREVIOUS,然后重启;重叠期间两个令牌都可使用。等所有客户端都使用新令牌后,删除 MCP_AUTH_TOKEN_PREVIOUS 并重启。对所有当前有效的令牌,比较过程始终采用时序安全方式。

暴力破解防护(fail2ban)。 自动生成的令牌具有 256 位随机性,因此无法通过猜测破解。如果你自行设置 MCP_AUTH_TOKEN,请确保令牌足够长且随机(例如 openssl rand -base64 32)——短或容易猜测的令牌才需要担心暴力破解。服务不会在进程内对失败的登录尝试进行速率限制或锁定;这项工作应交给防火墙级别的工具,例如 fail2ban,由它在请求到达服务之前封禁来源 IP。为方便实现这一点,每个被拒绝的请求都会向 stderr 输出一行结构化日志:

{"ts":"2026-06-18T17:28:00.370Z","level":"warn","msg":"auth_failed","client":"203.0.113.7","hadToken":true}

fail2ban/ 中附带了可直接使用的 fail2ban 配置:将 filter.d/ccu-mcp.conf 复制到 /etc/fail2ban/filter.d/,并将 jail.d/ccu-mcp.local 中的 jail 复制到 /etc/fail2ban/jail.d/(默认设置为 10 分钟内失败 5 次 → 封禁 1 小时)。服务将日志写入 stderr,因此请将 fail2ban 指向你收集日志的位置——作为 unit 运行时指向 journal(backend = systemd),或在重定向 stderr/使用 docker logs 时指向文件;jail 文件中对两种方式都有说明。需要设置 LOG_LEVEL=warn 或更低级别(默认为 info,可以使用;error 会屏蔽该日志行)。如果服务位于反向代理之后,记录的 IP 将是代理的 IP,因此请改为对代理的访问日志运行 fail2ban。

CORS 支持最初由 @marcinn2 在其分支 marcinn2/debmatic-mcp 中实现——感谢!

HTTPS

如果你的 CCU 使用 HTTPS(自签名证书也可以),请添加以下环境变量:

CCU_HTTPS=true
CCU_PORT=443

服务会自动接受自签名证书——由于 CCU 出厂时附带自签名证书,因此默认关闭证书验证(未验证连接运行时,服务会记录警告)。若要实际验证连接并消除 MITM 风险,有以下三种选择:

  • 固定证书指纹(适用于自签名设备证书,且最简单):将证书的 SHA-256 值(十六进制,可带或不带冒号)设置为 CCU_TLS_FINGERPRINT。除非 CCU 提供的证书与该值完全一致,否则连接会被拒绝。使用以下命令读取:
    echo | openssl s_client -connect "$CCU_HOST:443" 2>/dev/null | openssl x509 -noout -fingerprint -sha256
    
  • 信任 CA/自签名 PEM:将 CCU_CA_CERT 指向证书文件,以进行标准链验证。
  • 系统信任存储:如果你的 CCU 使用公开受信任的证书,请设置 CCU_TLS_VERIFY=true。

CCU_TLS_FINGERPRINT 的优先级高于 CCU_CA_CERT,而 CCU_CA_CERT 的优先级高于 CCU_TLS_VERIFY。

ccu-mcp init 会为你完成证书固定:它会显示 CCU 提供的证书,并在你确认后将指纹写入 env 文件;ccu-mcp doctor 会在之后重新检查固定的指纹(如果证书合法轮换,还会提供更新选项)。

配置

所有配置都通过环境变量完成:

变量默认值描述
CCU_HOST必填CCU 的主机名或 IP
CCU_PASSWORD必填CCU 管理员密码。必须设置;如果设备没有密码(全新安装的 OpenCCU),可以为空
CCU_USERAdminCCU 用户名
CCU_PORT80API 端口(使用 HTTPS 时为 443)
CCU_HTTPSfalse通过 HTTPS 连接(支持自签名证书)
CCU_TLS_VERIFYfalse根据系统信任存储验证 CCU 的 TLS 证书(适用于受公共机构信任的证书)
CCU_TLS_FINGERPRINT未设置通过 SHA-256 指纹(十六进制,可带冒号)固定 CCU 的自签名叶证书。优先于其他 TLS 选项
CCU_CA_CERT未设置用于验证证书链的 CCU CA/自签名 PEM 文件路径
CCU_TIMEOUT10000CCU 请求超时时间,单位为毫秒
CCU_SCRIPT_TIMEOUT30000HM Script 执行超时时间,单位为毫秒
LOG_LEVELinfoerror、warn、info 或 debug
CACHE_DIR/data设备类型缓存和会话的存储位置
CACHE_TTL86400缓存有效期,单位为秒(24 小时)
MCP_TRANSPORThttphttp 或 stdio(--stdio CLI 标志会覆盖此设置)
MCP_PORT3000HTTP 服务端口(仅适用于 HTTP 模式)
MCP_AUTH_TOKEN自动生成HTTP 模式的 Bearer 令牌;首次启动时生成并保存到 $CACHE_DIR/.env
MCP_AUTH_TOKEN_PREVIOUS未设置先前的 Bearer 令牌,在轮换重叠期间与 MCP_AUTH_TOKEN 一同接受;移除此项并重启即可结束重叠期。仅适用于显式令牌配置
MCP_AUTH_TOKEN_TTL_DAYS未设置(永不过期)自动生成的令牌有效期,单位为天(允许小数)。服务端会在令牌到期前不久于运行时自动轮换(新令牌会通过 stderr 通知);设置 MCP_AUTH_TOKEN 时忽略此项
MCP_AUTH_TOKEN_GRACE_HOURS24自动轮换后的重叠期,单位为小时;在此期间,刚被替换的令牌仍可使用
MCP_ALLOWED_ORIGINS未设置以逗号分隔的浏览器来源允许列表。未设置 = 不允许跨源浏览器访问(默认拒绝)。允许列表中的来源会原样反映在 Access-Control-Allow-Origin 中(绝不会是 *);该列表也用于 DNS 重绑定来源检查
MCP_ALLOWED_HOSTSMCP 端口上的 localhost/127.0.0.1/[::1]DNS 重绑定保护允许的额外 Host 值(以逗号分隔的 host:port);请添加客户端用于访问服务端的每个名称/IP(代理、容器 DNS 名称、普通服务端 IP)
MCP_HOST未设置(所有接口)HTTP 监听器的绑定地址;设置为 127.0.0.1 可限制为回环地址(例如部署在 TLS 终止代理后),同时也会关闭明文传输警告
MCP_TLS_CERT / MCP_TLS_KEY未设置PEM 证书/密钥路径。设置两者即可通过原生 HTTPS 提供 MCP;不设置则使用普通 HTTP。只设置其中一项会导致配置错误
MCP_ALLOW_PLAINTEXTfalse设置为 true,表示确认通过普通 HTTP 传输 Bearer 令牌,并关闭非回环地址的明文传输警告
CCU_RATE_LIMIT_BURST20发送到 CCU 的最大突发请求数
CCU_RATE_LIMIT_RATE10CCU 持续请求速率,单位为每秒
RESOURCE_POLL_INTERVAL60MCP 资源变更通知的轮询间隔,单位为秒

如需通过一台服务端驱动多个 CCU,请用命名配置替换这些扁平的 CCU_* 变量——详见下文的多个 CCU 目标。

命令行标志
ccu-mcp init           # interactive setup: probe the CCU, pin its TLS cert,
                       #   test the login, write an env file (default ./.env)
ccu-mcp doctor         # validate an env file end-to-end: reachability,
                       #   certificate pin, login, privilege level
ccu-mcp secret [prof]  # store ONE CCU password into an env file via a local
                       #   hidden prompt — name the target when the file
                       #   defines profiles, omit it for a single CCU (used by
                       #   the LLM-guided setup below; also the rotation path)
ccu-mcp --stdio        # serve over stdin/stdout (overrides MCP_TRANSPORT)
ccu-mcp --http         # serve over HTTP (default)
ccu-mcp --env <path>   # load configuration from a dotenv file (already-set
                       #   environment variables win); also accepted by
                       #   init/doctor/secret to pick the file they
                       #   write/check/update (default ./.env)
ccu-mcp --version      # print the installed version and exit
ccu-mcp --help         # print usage and exit

ccu-mcp init 会引导你配置一个或多个 CCU 目标(多个 CCU 目标)——它会先询问你是否需要配置多个目标,然后逐一询问每个目标的名称、端点、证书固定值、凭据和两个策略标志,并询问要将哪个目标设为启用状态。它会检测每个已配置用户的权限级别是 ADMIN 还是 USER(基于脚本的工具需要 ADMIN),最后提供一段可直接粘贴的 MCP 客户端配置片段。无需预先存在配置。任何检查失败时,ccu-mcp doctor 都会以非零状态码退出,因此也适用于脚本;如果 CCU 的证书确实已轮换,请在交互模式下运行,以便选择刷新固定值。操作示例:设置多个目标。

LLM 引导式设置(设置模式)

该向导还有一个对话版:先在 MCP 客户端中注册服务,再进行配置。使用 --stdio --env <path> 启动,且配置缺失或不完整时,服务会以设置模式启动——这是一个精简的 MCP 服务,仅公开四个 setup_* 工具(setup_status、setup_probe、setup_write_profile、setup_test)以及相关说明,让 LLM 通过普通聊天引导你完成相同的探测 → 固定证书 → 测试登录 → 写入流程。

{
  "mcpServers": {
    "ccu-mcp": {
      "command": "npx",
      "args": ["ccu-mcp", "--stdio", "--env", "/path/to/.env"]
    }
  }
}

然后只需提出请求:“设置我的 CCU 连接”。有一个刻意设计的例外:密码绝不会经过模型或聊天记录。setup_write_profile 没有密码参数;助手会给你一条命令,让你在终端中运行——npx ccu-mcp secret <profile> --env /path/to/.env,或者根据你的安装方式使用等效命令——它会在本地提示输入密码(关闭回显),并且只将密码写入文件(权限模式为 0600)。请复制工具输出的命令,而不是这里的命令:该命令会指定输出它的构建版本,因此不会误用缺少此子命令的旧版安装。setup_test 报告成功后,重新连接 MCP 服务,同一条客户端配置就会以完整配置启动服务。

这里也支持多个 CCU——说明这一点(“我有一个生产环境 CCU 和一个开发环境 CCU”),助手就会针对每个目标重复执行探测 → 写入 → 密钥流程:setup_write_profile 接受一个 name(以及 protected、readonly 和 makeDefault),并更新该目标,同时保留其他目标及其已存储的密码。每个目标都需要单独运行一次 ccu-mcp secret <name>;在所有已配置目标都设置好密码之前,服务会保持在设置模式:如果中途重新连接,会再次进入设置模式,并指出仍缺少密码的目标以及完成设置所需的确切 secret 命令。真正没有密码的 CCU 不属于缺少密码——将键写入空值(CCU_<NAME>_PASSWORD=)即可明确表示这一点。

设置模式仅支持 stdio(可写入配置文件的未配置 HTTP 端点会造成不可接受的攻击面);不带 --env 直接启动仍会明确报错,而不会静默地提供设置工具。

--version 和 --help 无需配置——可用它们检查已安装的副本究竟是什么版本,例如更新后:

$ npx ccu-mcp@latest --version
1.10.0

请注意,直接运行 npx ccu-mcp 会复用缓存于 ~/.npm/_npx 的副本,而不会重新从注册表解析;如果想获取最新版本,请指定 @latest(或清除该缓存)。

如何提供这些变量(内联、.env 或 export)

必需的 CCU_HOST / CCU_PASSWORD(以及其他所有变量)都是环境变量。任选以下一种方式提供即可,只需选一种:

  • 在 .mcp.json 中内联——使用上方 选项 A 中所示的 env 块。最简单,配置齐全。

  • Shell export——如上方快速开始所示。

  • .env 文件——将密钥保留在 .mcp.json 之外。使用服务自身的 --env 标志传入(ccu-mcp init 也会写入此配置并打印相应代码片段):

    {
      "mcpServers": {
        "ccu-mcp": {
          "command": "npx",
          "args": ["ccu-mcp", "--stdio", "--env", "/path/to/.env"]
        }
      }
    }
    

    (也可以在脚本路径前使用 Node 自身的 --env-file= 标志,但如果文件尚不存在,Node 会拒绝启动,而且该标志需要 dist/index.js 的完整路径。)

    将 .env.example 复制为 .env 并填写内容(其中说明了每个变量)。Docker 用户可以通过 docker run --env-file .env 或 compose 的 env_file: 传入同一文件。确保 .env 已加入 gitignore。

多个 CCU 目标(配置档)

默认情况下,上方的 CCU_* 变量用于配置单个 CCU。如需通过一个服务访问多个 CCU(例如 生产环境 + 开发环境),请改为定义命名配置档。与其他配置一样,可通过内联、.env 或 export 设置这些变量——参见上文:

CCU_PROFILES=prod,dev
CCU_DEFAULT_PROFILE=prod           # active at startup (defaults to the first listed)

CCU_PROD_HOST=ccu.example
CCU_PROD_USER=ai
CCU_PROD_PASSWORD=...
CCU_PROD_HTTPS=true
CCU_PROD_PROTECTED=true            # writes need confirm:true

CCU_DEV_HOST=127.0.0.1
CCU_DEV_PORT=18080
CCU_DEV_USER=Admin
CCU_DEV_PASSWORD=                  # may be empty (e.g. an OpenCCU dev box)

每个配置档使用与扁平变量相同的设置,变量名前缀为 CCU_<NAME>_(名称需大写,非字母数字字符替换为 _):HOST(必需)、PASSWORD(可以为空;与扁平变量 CCU_PASSWORD 不同,也可以完全省略,此时会按空值处理)、USER、PORT、HTTPS、TIMEOUT、SCRIPT_TIMEOUT、TLS_FINGERPRINT、CA_CERT、TLS_VERIFY,以及两个策略标志:

  • CCU_<NAME>_PROTECTED=true——除非调用时传入 confirm: true,否则写入工具会拒绝执行;传入后,本次会话期间对该目标的写入操作将获准。例外:每次调用 run_script 和 delete_system_variable 时都必须传入 confirm: true,它们不会因会话解锁而获准(脚本会绕过所有类型化工具的防护;删除操作无法恢复),且确认这两项操作不会解锁会话中的其他写入操作。
  • CCU_<NAME>_READONLY=true——写入工具将直接被拒绝。

如果未设置 CCU_PROFILES,则会将扁平的 CCU_* 变量作为单个 default 配置档使用(行为不变)。运行时,list_ccu_targets 会显示各个目标,get_connection_info 会报告当前活动目标,而 use_ccu 可用于切换目标。读取工具也接受可选的 target 参数,可在单次调用中从另一个 CCU 读取数据,而无需切换目标。

配置多个目标

使用向导。 ccu-mcp init 会先询问,然后针对每个目标依次收集名称 → 端点 → 证书固定值 → 凭据 → 策略标志,最后询问哪个目标作为当前活动目标启动:

$ npx ccu-mcp init --env ~/.config/ccu-mcp/.env
ccu-mcp setup — probes your CCU, pins its TLS certificate, tests the
login, and writes the result to /home/you/.config/ccu-mcp/.env.

Set up multiple CCU targets (e.g. prod/dev)? [y/N]: y
Profile name [prod]: prod
CCU hostname or IP: ccu.example
Probing ccu.example ...
  Found the CCU API on port 443 (HTTPS).
Use HTTPS? [Y/n]: y
Port [443]: 443
The CCU presents this TLS certificate:
  Subject: ccu.example
  Issuer:  ccu.example
  Valid:   Jun 19 21:37:09 2026 GMT — Jun 16 21:37:09 2036 GMT
  SHA-256: 90:0C:4C:F2:53:22:E7:78:...:40:ED:16:95:6E:BB:B1:53
Pin this certificate's fingerprint (recommended)? [Y/n]: y
CCU user [Admin]: ai
CCU password (input hidden):
Testing login ...
  Login OK (CCU 3.87.6.20260614) — privilege level ADMIN: all tools available.
Protect this target (write tools then require confirm:true)? [y/N]: y
Make this target read-only (write tools refused entirely)? [y/N]: n
Add another CCU target? [y/N]: y
Profile name: dev
CCU hostname or IP: 192.168.1.50
Probing 192.168.1.50 ...
  Found the CCU API on port 80 (HTTP).
Use HTTPS? [Y/n]: n
Port [80]: 80
CCU user [Admin]: Admin
CCU password (input hidden):
Testing login ...
  Login OK (CCU 3.87.6.20260614) — privilege level ADMIN: all tools available.
Protect this target (write tools then require confirm:true)? [y/N]: n
Make this target read-only (write tools refused entirely)? [y/N]: n
Add another CCU target? [y/N]: n
Default target (prod/dev) [prod]: prod

Wrote /home/you/.config/ccu-mcp/.env (mode 0600).

它写入的文件采用配置文件格式,每个目标对应一个带注释的区块;向导只会重写这些键,因此文件中的其他内容(LOG_LEVEL、 CACHE_DIR、MCP_*)都会保留:

# Written by ccu-mcp setup — https://github.com/claymore666/ccu-mcp#configuration
CCU_PROFILES=prod,dev
CCU_DEFAULT_PROFILE=prod

# --- target: prod ---
CCU_PROD_HOST=ccu.example
CCU_PROD_PORT=443
CCU_PROD_HTTPS=true
CCU_PROD_USER=ai
CCU_PROD_PASSWORD="..."
CCU_PROD_TLS_FINGERPRINT=90:0C:4C:F2:53:22:E7:78:...:40:ED:16:95:6E:BB:B1:53
CCU_PROD_PROTECTED=true

# --- target: dev ---
CCU_DEV_HOST=192.168.1.50
CCU_DEV_PORT=80
CCU_DEV_HTTPS=false
CCU_DEV_USER=Admin
CCU_DEV_PASSWORD=""

在已有文件上重新运行 init 时,向导会询问是否替换这些设置;添加第三个目标意味着要重新遍历整个列表,因此若只是临时添加目标,请编辑文件(或使用 setup_write_profile,它会更新或插入单个目标),然后运行 doctor。

每个目标一个密码。 ccu-mcp secret 只会写入一个键,因此需要提供目标名称——init 会在流程中提示输入密码,但 LLM 引导的流程和之后的每次轮换都要通过 secret 完成。在配置文件上不提供名称时,它会列出所需的运行命令:

$ ccu-mcp secret --env ~/.config/ccu-mcp/.env
This file configures named targets (prod, dev) — one password each:
  node /home/you/.local/bin/ccu-mcp secret prod --env /home/you/.config/ccu-mcp/.env
  node /home/you/.local/bin/ccu-mcp secret dev --env /home/you/.config/ccu-mcp/.env

$ ccu-mcp secret prod --env ~/.config/ccu-mcp/.env
CCU password for [email protected] (input hidden):
Wrote CCU_PROD_PASSWORD to /home/you/.config/ccu-mcp/.env (mode 0600).

这些提示有意显示为 node <path>,而不是 ccu-mcp:该路径对应打印提示的构建版本,因此复制命令不会误用缺少此子命令的旧版本。secret 在扁平的单 CCU 文件中会拒绝目标名称,在配置文件中会拒绝未知目标,因此绝不会写入错误的键。

一次性验证所有内容。 doctor 会检查每个目标的配置、连通性、证书固定值、登录状态和权限级别;任一检查失败都会以非零状态码退出:

$ ccu-mcp doctor --env ~/.config/ccu-mcp/.env
ccu-mcp doctor — checking /home/you/.config/ccu-mcp/.env
  ✓ configuration loads: 2 target(s), default "prod"

Target "prod" — ccu.example:443 (HTTPS)
  ✓ CCU API reachable
  ✓ pinned TLS fingerprint matches the presented certificate
  ✓ login OK as "ai" (CCU 3.87.6.20260614) — privilege level ADMIN

Target "dev" — 192.168.1.50:80 (HTTP)
  ✓ CCU API reachable
  ✓ login OK as "Admin" (CCU 3.87.6.20260614) — privilege level ADMIN

All checks passed.

在客户端中。 一个 MCP 服务条目即可服务所有目标——目标列表由 --env 文件提供,因此添加 CCU 时无需更改客户端配置:

{
  "mcpServers": {
    "ccu-mcp": {
      "command": "npx",
      "args": ["ccu-mcp", "--stdio", "--env", "/home/you/.config/ccu-mcp/.env"]
    }
  }
}

然后在聊天中询问:“配置了哪些 CCU?”(list_ccu_targets)、“读取 dev 上客厅的温度”(单次调用时指定 target: "dev")、“切换到 dev”(use_ccu)。如上所示,设置 CCU_PROD_PROTECTED=true 后,首次对 prod 执行写入操作时会要求提供 confirm: true;确认后,该目标在本次会话的剩余时间内会解除锁定——但 run_script 和 delete_system_variable 除外,这两项每次都会询问。

配置错误

有些错误会导致服务器在启动时停止,而不是忽略它们。否则,这些错误会一直被静默忽略,直到很久以后才导致失败,因此退出是有意为之的。ccu-mcp doctor 会在不启动服务器的情况下,针对 env 文件报告同样的错误,同时执行实时检查(可达性、证书固定、登录)。有一个例外:使用 --stdio --env <path> 启动时,如果配置有误,服务器会进入设置模式(并在服务器的说明中显示错误),而不是退出,这样就可以通过对话修复配置:

消息原因及其致命性
CCU_HOST environment variable is required未配置 CCU(且未设置 CCU_PROFILES)。
CCU_PASSWORD environment variable is required该变量不存在。空值是可接受的——全新的 OpenCCU 设备没有 Admin 密码——因此这表示“尚未设置”。这会让单 CCU 设置模式服务器一直处于设置模式,直到 ccu-mcp secret 保存密码。
no password stored yet for target <name>配置文件形式的对应错误,仅限设置模式:CCU_<NAME>_PASSWORD 不存在。已加载的配置仍会将缺失的键读取为空值(保持不变,因此 OpenCCU 开发目标仍可正常工作)——但在判断设置是否完成时,不存在表示“尚未输入”,因此服务器会继续处于设置模式,并打印用于完成设置的 ccu-mcp secret <name> 命令。写入 CCU_<NAME>_PASSWORD= 可明确声明密码为空是有意为之。
CCU_DEFAULT_PROFILE is set but CCU_PROFILES is not配置文件设置遗留的内容。忽略它会让写入操作指向扁平配置中的 CCU_HOST 设备,而 env 文件却显示存在一个命名目标。
CCU_PROFILES is set but lists no profile names值为空,或仅包含逗号。
CCU_PROFILES lists "<name>" more than once配置文件名称重复。
... both map to the same env prefix CCU_<P>_* — rename one不同名称经过规范化后可能发生冲突:prod-a 和 prod.a 都会读取 CCU_PROD_A_*,因此它们会被静默地视为同一个目标。
CCU_DEFAULT_PROFILE="x" is not one of CCU_PROFILES (...)启动配置文件名称拼写错误。
profile "<name>" is missing CCU_<P>_HOST每个配置文件都必须指定主机;密码可以为空。
TLS_FINGERPRINT/CA_CERT/TLS_VERIFY is set but HTTPS is disabled验证代码路径仅适用于 HTTPS。忽略这些设置会让你误以为连接已通过验证,而凭据实际上是明文传输的。请设置 CCU_HTTPS=true(或 CCU_<NAME>_HTTPS=true),或者移除这些设置。
MCP_TLS_CERT and MCP_TLS_KEY must both be set (or both unset)只设置部分 TLS 配置无法提供 HTTPS 服务。
MCP_TRANSPORT must be "http" or "stdio"大小写敏感。像 STDIO 这样的拼写错误不得静默地选择 HTTP,导致启动 stdio 的客户端永远等待。
<VAR> must be a positive integer端口、超时、CACHE_TTL、速率限制、RESOURCE_POLL_INTERVAL。整个值必须由数字组成——CCU_TIMEOUT=30s 会被拒绝,而不是被读取为 30 毫秒;30.5 或 1e4 也会被拒绝,而不是截断处理。
<VAR> must be a positive number两项时长设置:MCP_AUTH_TOKEN_TTL_DAYS 和 MCP_AUTH_TOKEN_GRACE_HOURS,这两项设置允许使用小数值。
<VAR> must be "true" or "false"任意布尔设置(CCU_HTTPS、CCU_TLS_VERIFY、CCU_<NAME>_PROTECTED、CCU_<NAME>_READONLY、MCP_ALLOW_PLAINTEXT)。首尾空格和大小写均可;不接受 yes、1 和 on,因为将它们视为false会悄然关闭保护。
CCU_CA_CERT could not be read路径错误,或服务器用户无权读取该文件。

无需任何配置即可使用 ccu-mcp --version 和 --help,因此在排查这些问题时仍可使用它们。

工具

28 个工具,按实际用途分类:

查找 — list_devices、list_rooms、list_functions、list_interfaces、list_programs、list_system_variables、list_links、describe_device_type

读取状态 — get_value、get_values(批量)、get_paramset

更改设置 — set_value、put_paramset、set_system_variable、create_system_variable、delete_system_variable、assign_channel、unassign_channel、execute_program

检查运行状况 — get_service_messages、acknowledge_service_messages、get_rssi、get_system_info

切换目标 — list_ccu_targets、get_connection_info、use_ccu(多 CCU 配置;见上文)

其他 — help(上下文感知)、run_script(原始 HomeMatic Script,用于批量操作、重命名设备/通道、查询房间成员关系,或处理其他工具未涵盖的任何事项)

大多数工具会根据设备地址自动解析接口和值类型——你无需了解设备使用的是 BidCos-RF 还是 HmIP-RF。

资源和提示词

除了工具外,服务还会提供 MCP 资源——可浏览的 JSON 快照,客户端可以将其附加为上下文:

homematic://devices、homematic://rooms、homematic://functions、homematic://programs、homematic://sysvars、homematic://interfaces、homematic://device-types、homematic://system

服务会在后台轮询 CCU(每隔 RESOURCE_POLL_INTERVAL 秒一次),并向通过 resources/subscribe 订阅了资源的客户端发送这些资源内容发生变化时的 notifications/resources/updated 通知。

服务还附带 MCP 提示词——可从支持提示词的客户端调用的现成工作流(例如,在 Claude Code 中作为斜杠命令使用):

  • check-windows — 是否有窗户或门处于打开状态?
  • room-status — 指定房间的完整状态报告
  • set-heating — 设置房间的目标温度
  • good-night — 为夜晚做好准备
  • diagnostics — 检查设备问题
  • device-info — 设备功能和参数的详细信息

room 和 device 参数支持自动补全:支持 completion/complete 的客户端会提供此 CCU 实际拥有的房间和设备名称, 因此无需记住房间在 WebUI 中的拼写方式。

MCP 协议修订版本

服务实现了修订版本 2025-11-25,并会为较旧的客户端协商降级(2025-06-18、2025-03-26、2024-11-05 均可接受)——你 无需使用特定版本的客户端。服务会声明 tools、resources (含 subscribe)、prompts、completions 和 logging。

修订版本 2026-07-28——每个请求的协议版本、server/discover—— 尚未实现:编写本文时,此服务所基于的 TypeScript SDK 尚不支持该版本,而此服务遵循该 SDK。

工作原理

服务通过 CCU 的 JSON-RPC API(与 WebUI 使用的相同 API)进行通信。启动时,它会:

  1. 登录并缓存会话(重启后会复用)
  2. 从磁盘加载设备类型缓存(或在后台预热缓存)
  3. 通过 stdio 或 HTTP 启动 MCP 服务

设备类型架构会缓存在本地,因此 AI 无需每次都访问 CCU,即可查询有效参数、类型和值范围。

返回的值使用原生类型——21.5 而不是 "21.500000",true 而不是 "true"。

已测试的设备

此服务已在生产环境中的 debmatic 安装上进行测试,涉及以下设备:

  • HmIP-eTRV-2 / eTRV-2 I9F(散热器恒温器)
  • HmIP-STHD(带湿度功能的墙面恒温器)
  • HmIP-WTH-2(墙面恒温器)
  • HmIP-SWDO-I(门窗触点)
  • HmIP-STHO(室外温度/湿度传感器)
  • HmIP-ESI(电能/燃气表)
  • HmIP-FALMOT-C12(地暖控制器)
  • HmIP-HEATING(虚拟供暖组)
  • HmIP-WRCC2(墙面遥控器)
  • HM-PB-6-WM55(BidCos 六键遥控器)
  • RPI-RF-MOD(无线模块)

其他设备类型也应该可以使用——服务会向 CCU 查询参数说明,而不是维护静态设备数据库。

更新日志

发行说明——包括升级前需检查的行为变更 (更严格的配置验证、/health 响应结构、按会话确认写入、 重试语义)——请参阅 CHANGELOG.md。

获取帮助与参与贡献

  • 遇到故障,或有功能建议? 请提交议题: github.com/claymore666/ccu-mcp/issues
  • 有问题、需要设置帮助,或想讨论 HomeMatic? 请访问 HomeMatic 论坛——维护者在论坛上的用户名是 claymore666。
  • 发现安全问题? 请不要公开发布。有关私下报告的方式,请参阅 SECURITY.md。
  • 想提交补丁? CONTRIBUTING.md 介绍了设置方法、 目标分支、编码规范和测试政策。

所有参与者都应遵守 行为准则。

项目文档
文档内容
ROADMAP.md项目的发展方向,以及明确不会实现的内容
GOVERNANCE.md决策者、决策方式,以及已知的连续性缺口
SECURITY.md报告方式、安全要求、威胁模型
docs/architecture.md高层设计和请求流程
docs/assurance-case.md安全要求成立的原因及相关证据
CHANGELOG.md各个版本的变更内容

相关项目

  • OpenCCU — 由社区维护、无云服务的 CCU 固件,适用于 Raspberry Pi、x86/ARM 以及 CCU3/ELV-Charly 硬件(原名 RaspberryMatic;基于 OCCU 框架构建)
  • debmatic — 在 Debian、Ubuntu、Raspberry Pi OS、Armbian 上运行 HomeMatic
  • OCCU — eQ-3 原版 Open CCU SDK(上游 HomeMatic 软件);目前正逐步由社区维护的 OpenCCU 取代
  • MCP — Model Context Protocol 规范
  • ccu-ai-mcp,由 Mathias (mdzio) 开发 — 一个面向 HomeMatic 的同类 MCP 服务,采用刻意不同且优雅的方案(精简的 Go 核心搭配用户自定义的 HM-Script 工具)。请参阅他在 HomeMatic 论坛 上发布的介绍。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

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

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