debmatic-mcp
The debmatic-mcp server connects an AI assistant (like Claude or Cursor) to a HomeMatic smart home system (debmatic, CCU3, or RaspberryMatic), enabling discovery, monitoring, and control of smart home devices through 18 tools, resources, and prompts.
š Discover & List
list_devicesā Discover all devices with channels, types, and addresses; filter by room, function, type, or namelist_rooms/list_functionsā List rooms and function groups (e.g. Heating, Lighting) with assigned channelslist_interfacesā List available communication interfaces (BidCos-RF, HmIP-RF, VirtualDevices, etc.)list_programs/list_system_variablesā List automation programs and system variables, with optional name filteringdescribe_device_typeā Get the full channel/datapoint schema for a device type, including parameters, types, and value ranges
š Read State
get_valueā Read a single datapoint value from a device channel (e.g. temperature, window state)get_valuesā Bulk-read datapoint values for multiple channels, or filter by room/functionget_paramsetā Read all parameters for a channel (VALUES, MASTER, or LINK paramsets)
āļø Control Devices & Automation
set_valueā Set a single datapoint value (e.g. set thermostat temperature, toggle a switch)put_paramsetā Write multiple parameters at once (e.g. update a thermostat weekly profile)set_system_variableā Update a system variable valueexecute_programā Trigger an automation program on the CCU
𩺠Monitor Health
get_service_messagesā View active service messages: low battery alerts, unreachable devices, etc.get_system_infoā Retrieve CCU system info: firmware version, serial number, and addresses
š ļø Advanced & Usability
run_scriptā Execute arbitrary HomeMatic Script on the CCU for bulk operations or anything not covered by other toolshelpā Context-aware help: general guide, tool-specific usage, or device type capabilitiesBrowsable JSON resources (devices, rooms, functions, programs, sysvars, etc.) that clients can attach as context
Built-in prompt workflows for common tasks like checking windows, setting heating, good-night routines, and diagnostics
Automatic interface and value type resolution for most operations
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@debmatic-mcpWhat's the temperature in the living room?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ccu-mcp
Talk to your HomeMatic smart home from Claude, Cursor, or any MCP client.
ccu-mcp connects to the CCU's built-in JSON-RPC API and exposes your devices, rooms, programs, and system variables as MCP tools. No addons, no XML-API, no cloud ā just a direct connection to the CCU on your local network.
Works with any HomeMatic CCU: debmatic (HomeMatic on Debian), a CCU3, or OpenCCU (formerly RaspberryMatic) ā anything that exposes the standard /api/homematic.cgi endpoint.
What can it do?
Ask your AI assistant things like:
"What's the temperature in the bathroom?"
"Are any windows open?"
"Set the living room heating to 21 degrees"
"Show me all devices with low battery"
"What's the gas meter reading?"
"Which devices have low battery or haven't been seen in a long time?"
"Find all channels whose names don't match their device name"
"Rename all devices to follow a consistent naming convention with floor labels (UG/OG/EG)"
"Which room is the window sensor in?"
The MCP server handles device discovery, type resolution, session management, and value conversion ā the AI just calls the tools.
Related MCP server: Home Assistant MCP Server
Prerequisites
A running HomeMatic CCU (debmatic, CCU3, or OpenCCU ā formerly RaspberryMatic) reachable on your network
The CCU's admin username and password (the same credentials you use to log into the WebUI)
Node.js 24+ (for running from source or stdio mode) or Docker
Quick start
export CCU_HOST=your-ccu-hostname-or-ip
export CCU_PASSWORD=your-ccu-admin-password
npx ccu-mcp --stdioIf it prints server_ready to stderr, it's working. Press Ctrl+C to stop. Now set it up in your MCP client ā see below.
A cache_save_failed ⦠mkdir '/data' line alongside it is harmless here but
worth fixing for real use: CACHE_DIR defaults to /data (the Docker layout),
so outside a container the device-type cache and the CCU session are never
persisted between runs. Point it somewhere writable:
export CACHE_DIR="$HOME/.cache/ccu-mcp" (or the same key in your .env /
env block).
Prefer a guided setup? npx ccu-mcp init probes your CCU, pins its TLS
certificate, tests the login, writes a ready-to-use .env file, and prints the
matching MCP client config ā see Command-line flags.
Installation
There are two ways to run this: stdio (the server runs as a subprocess of your MCP client) or HTTP (the server runs standalone in Docker and clients connect over the network). Pick one.
Option A: stdio (direct, simplest)
This is the easiest setup. Your MCP client (Claude Code, Cursor, etc.) starts the server as a child process ā no Docker, no network config, no auth tokens.
For Claude Code, create a .mcp.json file in your project directory (or any directory where you'll use Claude Code):
{
"mcpServers": {
"ccu-mcp": {
"command": "npx",
"args": ["ccu-mcp", "--stdio"],
"env": {
"CCU_HOST": "your-ccu-hostname-or-ip",
"CCU_PASSWORD": "your-ccu-admin-password"
}
}
}
}Replace your-ccu-hostname-or-ip with your CCU's hostname (like homematic-ccu3) or IP (like 192.168.1.50), and your-ccu-admin-password with the password you use to log into the CCU WebUI.
Restart Claude Code. Run /mcp to check it connected. You should see ccu-mcp in the list.
Alternatively, use the Claude Code CLI:
claude mcp add ccu-mcp -- npx ccu-mcp --stdioOption B: Docker (standalone HTTP server)
Use this if you want the server running independently ā for example on a home server, accessible to multiple clients, or when your MCP client supports HTTP remotes.
1. Start the container. Images are published to GHCR for linux/amd64 and
linux/arm64 (so a Raspberry Pi next to the CCU works), built natively on each
architecture and attested ā gh attestation verify oci://ghcr.io/claymore666/ccu-mcp:latest --repo claymore666/ccu-mcp
proves the image came from this repository's release workflow.
docker pull ghcr.io/claymore666/ccu-mcp:latestEvery release also publishes its own X.Y.Z tag ā pin that instead of latest
if you'd rather upgrade deliberately. To build from source instead:
git clone https://github.com/claymore666/ccu-mcp.git && cd ccu-mcp
docker build -t ghcr.io/claymore666/ccu-mcp .Then run it:
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_HOSTSis required for remote clients. The server's DNS-rebinding protection rejects any request whoseHostheader isn't on the allowlist ā by default onlylocalhost/127.0.0.1/[::1]on the MCP port. Set it to every name/IP clients will use to reach the server (comma-separated,host:port). Without it, the local health check works but every remote MCP request gets 403 Invalid Host header.
2. Get the auth token. The server generates a random bearer token on first startup and saves it inside the container's data volume. You need this token to authenticate your MCP client. Grab it with:
docker exec ccu-mcp grep MCP_AUTH_TOKEN /data/.envThis prints something like MCP_AUTH_TOKEN=e96suzi1iG0H-GPif6K2.... The part after = is your token.
3. Configure your MCP client. If your client uses .mcp.json, add the HTTP server:
{
"mcpServers": {
"ccu-mcp": {
"url": "http://your-server-ip:3000",
"headers": {
"Authorization": "Bearer PASTE-YOUR-TOKEN-HERE"
}
}
}
}To inject the token automatically (requires 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.jsonThis only updates the ccu-mcp entry ā other servers in your .mcp.json are left alone.
4. Check it's healthy:
curl http://localhost:3000/healthBrowser-based clients (CORS)
By default the HTTP server sends no CORS headers, so a random web page can't drive a local instance. To let browser-based MCP clients like MCP Inspector connect directly, set MCP_ALLOWED_ORIGINS to a comma-separated allowlist of trusted origins (e.g. https://app.example,http://localhost:6274). A request whose Origin is on the list gets that exact origin reflected in Access-Control-Allow-Origin ā never the wildcard *, which would let any site drive a local instance that controls real CCU hardware. A request from any other origin gets no CORS headers (the browser blocks it) and is rejected server-side by DNS-rebinding protection. Authentication is always enforced regardless: every MCP request needs the bearer token.
The HTTP transport also has DNS-rebinding protection on by default: it rejects requests whose Host header isn't localhost/127.0.0.1/[::1] on the configured port. If you reach the server under another hostname or IP (reverse proxy, container DNS name, the server's LAN address), list those hosts in MCP_ALLOWED_HOSTS or legitimate requests get a 403.
TLS. The bearer token travels in the request, so anything beyond loopback should be encrypted. You have two options: terminate TLS at a reverse proxy (Caddy/nginx) in front and bind the server to loopback (MCP_HOST=127.0.0.1), or let the server serve HTTPS itself by setting MCP_TLS_CERT and MCP_TLS_KEY to a PEM cert/key pair. Plain HTTP is still fully supported ā it stays the zero-config default ā but the server logs a warning at startup when it's serving the token over unencrypted HTTP on a non-loopback bind; set MCP_ALLOW_PLAINTEXT=true to acknowledge that and silence it.
Token rotation & expiry. By default the bearer token lives forever. Two optional, composable controls let you rotate it without dropping clients:
Auto-generated token ā set
MCP_AUTH_TOKEN_TTL_DAYS(fractional days allowed) to give the generated token a lifetime. The server rotates it automatically at runtime shortly before it lapses (no restart needed; also on startup if it expired while the server was down), prints the new token on stderr, and keeps the just-replaced token validating forMCP_AUTH_TOKEN_GRACE_HOURS(default 24) so in-flight clients survive the swap. To force a rotation sooner, delete$CACHE_DIR/.env(or just itsMCP_AUTH_TOKENline) and restart.Explicit token ā when you set
MCP_AUTH_TOKENyourself, you own its lifetime (TTL doesn't apply). To rotate, put the new token inMCP_AUTH_TOKEN, move the old one toMCP_AUTH_TOKEN_PREVIOUS, and restart; both are accepted during the overlap. DropMCP_AUTH_TOKEN_PREVIOUSand restart once every client is on the new token. Comparison stays timing-safe across every currently-valid token.
Brute-force protection (fail2ban). The auto-generated token is 256 bits of randomness, so guessing it is infeasible. If you set MCP_AUTH_TOKEN yourself, make it long and random (e.g. openssl rand -base64 32) ā a short or guessable token is the one case brute force matters. The server does not rate-limit or lock out failed logins in-process; that job belongs to a firewall-level tool like fail2ban, which bans the source IP before the request ever reaches the server. To make that easy, every rejected request logs a structured line to stderr:
{"ts":"2026-06-18T17:28:00.370Z","level":"warn","msg":"auth_failed","client":"203.0.113.7","hadToken":true}Ready-to-use fail2ban config ships in fail2ban/: copy filter.d/ccu-mcp.conf to /etc/fail2ban/filter.d/ and the jail in jail.d/ccu-mcp.local to /etc/fail2ban/jail.d/ (it defaults to 5 failures in 10 minutes ā 1-hour ban). The server logs to stderr, so point fail2ban at wherever you collect it ā the journal (backend = systemd) when run as a unit, or a file when you redirect stderr/docker logs; both are spelled out in the jail file. Requires LOG_LEVEL=warn or lower (info, the default, is fine; error suppresses the line). Behind a reverse proxy the logged IP is the proxy's, so run fail2ban against the proxy's access log instead.
CORS support was first implemented by @marcinn2 in his fork marcinn2/debmatic-mcp ā thanks!
HTTPS
If your CCU uses HTTPS (self-signed certificates are fine), add these environment variables:
CCU_HTTPS=true
CCU_PORT=443The server accepts self-signed certificates automatically ā certificate verification is off by default because CCUs ship with self-signed certs (the server logs a warning when running unverified). To actually verify the connection and close the MITM gap, you have three options:
Pin the fingerprint (simplest for a self-signed appliance cert): set
CCU_TLS_FINGERPRINTto the cert's SHA-256 (hex, with or without colons). The connection is rejected unless the CCU presents exactly that certificate. Read it with:echo | openssl s_client -connect "$CCU_HOST:443" 2>/dev/null | openssl x509 -noout -fingerprint -sha256Trust a CA/self-signed PEM: point
CCU_CA_CERTat the certificate file for standard chain validation.System trust store: if your CCU has a publicly-trusted certificate, set
CCU_TLS_VERIFY=true.
CCU_TLS_FINGERPRINT takes precedence over CCU_CA_CERT, which takes precedence over CCU_TLS_VERIFY.
ccu-mcp init does the pinning for you: it shows the certificate the CCU
presents and writes the fingerprint into the env file on confirmation, and
ccu-mcp doctor re-checks the pin later (offering a refresh after a
legitimate certificate rotation).
Configuration
All configuration is via environment variables:
Variable | Default | Description |
| required | Hostname or IP of your CCU |
| required | CCU admin password. Must be set, but may be empty for a box without one (a fresh OpenCCU) |
|
| CCU username |
|
| API port ( |
|
| Connect via HTTPS (self-signed certs supported) |
|
| Verify the CCU's TLS certificate against the system trust store (for a publicly-trusted cert) |
| unset | Pin the CCU's self-signed leaf cert by its SHA-256 fingerprint (hex, colons optional). Takes precedence over the other TLS options |
| unset | Path to the CCU's CA/self-signed PEM for chain validation |
|
| CCU request timeout in milliseconds |
|
| HM Script execution timeout in milliseconds |
|
|
|
|
| Where to store device type cache and session |
|
| Cache lifetime in seconds (24h) |
|
|
|
|
| HTTP server port (HTTP mode only) |
| auto-generated | Bearer token for HTTP mode; generated and saved to |
| unset | Previous bearer token, accepted alongside |
| unset (never expires) | Lifetime of the auto-generated token, in days (fractional allowed). The server auto-rotates it at runtime shortly before expiry (new token announced on stderr); ignored when |
|
| Overlap (hours) after an auto-rotation during which the just-replaced token is still accepted |
| unset | Comma-separated allowlist of browser origins. Unset = no cross-origin browser access (default-deny). An allowlisted origin is reflected exactly in |
|
| Extra |
| unset (all interfaces) | Bind address for the HTTP listener; set |
| unset | PEM cert/key paths. Set both to serve MCP over HTTPS natively; leave unset for plain HTTP. Setting only one is a configuration error |
|
| Set |
|
| Max burst of requests sent to the CCU |
|
| Sustained CCU requests per second |
|
| Seconds between polls for MCP resource change notifications |
To drive several CCUs from one server, these flat CCU_* vars are replaced
by named profiles ā see Multiple CCU targets
below.
Command-line flags
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 exitccu-mcp init walks through one or more CCU targets (profiles) ā
it asks up front whether you want several, then loops over name, endpoint,
certificate pin, credentials and the two policy flags per target and asks
which one starts active. It detects whether each configured user is ADMIN- or
USER-level (script-based tools need ADMIN), and ends with a ready-to-paste MCP
client snippet. It needs no pre-existing configuration. ccu-mcp doctor exits
non-zero when any check fails, so it also works in scripts; run it
interactively to be offered a pin refresh when the CCU's certificate
legitimately rotated. Worked example:
Setting up several targets.
LLM-guided setup (setup mode)
The wizard has a conversational twin: register the server in an MCP client
before configuring it. Started with --stdio --env <path> and a missing or
incomplete configuration, the server comes up in setup mode ā a minimal MCP
server exposing only four setup_* tools (setup_status, setup_probe,
setup_write_profile, setup_test) plus instructions that let the LLM walk
you through the same probe ā pin ā test-login ā write flow in plain chat.
{
"mcpServers": {
"ccu-mcp": {
"command": "npx",
"args": ["ccu-mcp", "--stdio", "--env", "/path/to/.env"]
}
}
}Then just ask: "set up my CCU connection". One deliberate exception: the
password never travels through the model or the chat transcript.
setup_write_profile has no password parameter; instead the assistant hands
you a one-liner to run in a terminal ā npx ccu-mcp secret <profile> --env /path/to/.env, or the equivalent for however you installed it ā which prompts
locally with echo off and writes only the password into the file (mode 0600).
Copy the command the tool prints rather than this one: it names the build that
printed it, so it cannot land on an older install that lacks the subcommand.
Once setup_test reports green, reconnect the MCP server and the identical
client entry starts it fully configured.
Several CCUs work here too ā say so ("I have a prod and a dev CCU") and the
assistant repeats probe ā write ā secret per target: setup_write_profile
takes a name (plus protected, readonly and makeDefault) and upserts
that one target, preserving the others and their already-stored passwords.
Each target needs its own ccu-mcp secret <name> run, and the server stays in
setup mode until every configured target has one: reconnecting halfway through
lands you back in setup mode, naming the target still missing a password and
the exact secret command that finishes it. A CCU that genuinely has no
password is not a missing one ā write the key with an empty value
(CCU_<NAME>_PASSWORD=) to say so deliberately.
Setup mode is stdio-only (an unconfigured HTTP endpoint that writes config
files would be an unacceptable surface), and a bare start without --env
still fails loudly instead of silently serving setup tools.
--version and --help need no configuration ā use them to check what an
installed copy actually is, e.g. after updating:
$ npx ccu-mcp@latest --version
1.10.0Note that a bare npx ccu-mcp reuses the copy cached in ~/.npm/_npx without
re-resolving against the registry; pin @latest (or clear that cache) when you
want the newest release.
How to supply these (inline, .env, or export)
The required CCU_HOST / CCU_PASSWORD (and everything else) are environment
variables. Provide them in whichever of these you prefer ā you need just one:
Inline in
.mcp.jsonā theenvblock shown in Option A above. Simplest; self-contained.Shell
exportā as in Quick start above.A
.envfile ā keeps secrets out of.mcp.json. Pass it with the server's own--envflag (this is also whatccu-mcp initwrites and the snippet it prints):{ "mcpServers": { "ccu-mcp": { "command": "npx", "args": ["ccu-mcp", "--stdio", "--env", "/path/to/.env"] } } }(Node's own
--env-file=flag before the script path works too, but node refuses to start when that file doesn't exist yet, and it needs the full path todist/index.js.)Copy
.env.exampleto.envand fill it in (it documents every variable). Docker users can pass the same file withdocker run --env-file .envor compose'senv_file:. Keep.envgitignored.
Multiple CCU targets (profiles)
By default the CCU_* vars above configure a single CCU. To reach several CCUs
(e.g. prod + dev) from one server, define named profiles instead. Set these
the same way as any other config (inline, .env, or export ā see above):
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)Each profile takes the same settings as the flat vars, prefixed
CCU_<NAME>_ (name upper-cased, non-alphanumerics ā _): HOST (required),
PASSWORD (may be empty ā and, unlike the flat CCU_PASSWORD, may also be
left out entirely, which reads as empty), USER, PORT, HTTPS, TIMEOUT,
SCRIPT_TIMEOUT, TLS_FINGERPRINT, CA_CERT, TLS_VERIFY ā plus two policy
flags:
CCU_<NAME>_PROTECTED=trueā write tools refuse unless called withconfirm: true, which unlocks writes to that target for the rest of the session. Exception:run_scriptanddelete_system_variablerequireconfirm: trueon every call ā they never ride on the session unlock (scripts bypass all typed-tool guards; deletion is unrecoverable), and confirming them does not unlock the session for other writes.CCU_<NAME>_READONLY=trueā write tools are refused outright.
With CCU_PROFILES unset, the flat CCU_* vars are used as a single default
profile (unchanged behavior). At runtime, list_ccu_targets shows the targets,
get_connection_info reports the active one, and use_ccu switches it. Read
tools also accept an optional target to read from another CCU for a single call
without switching.
Setting up several targets
With the wizard. ccu-mcp init asks up front, then loops over name ā
endpoint ā certificate pin ā credentials ā policy flags per target, and ends
by asking which one starts active:
$ 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).The file it writes is the profile form, one commented block per target ā and
the wizard rewrites only these keys, so anything else in the file (LOG_LEVEL,
CACHE_DIR, MCP_*) survives:
# 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=""Rerunning init on an existing file offers to replace those settings; adding a
third target means walking the whole list again, so for a one-off addition edit
the file (or use setup_write_profile, which upserts a single target) and then
run doctor.
One password per target. ccu-mcp secret writes exactly one key, so it
takes the target name ā init prompts for passwords inline, but the
LLM-guided flow and every later rotation go
through secret. Called without a name on a profile file it lists the runs you
need:
$ 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 ai@ccu.example (input hidden):
Wrote CCU_PROD_PASSWORD to /home/you/.config/ccu-mcp/.env (mode 0600).Those hints come out as node <path> rather than ccu-mcp on purpose: the
path is the build that printed them, so copying the line cannot land on some
older copy that lacks the subcommand. secret refuses a name against a flat
single-CCU file, and refuses an unknown one against a profile file, so it can
never write the wrong key.
Verify everything at once. doctor walks every target ā configuration,
reachability, pin, login and privilege level ā and exits non-zero if any check
fails:
$ 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.In the client. One MCP server entry serves all targets ā the --env file
carries the roster, so nothing about the client config changes when you add a
CCU:
{
"mcpServers": {
"ccu-mcp": {
"command": "npx",
"args": ["ccu-mcp", "--stdio", "--env", "/home/you/.config/ccu-mcp/.env"]
}
}
}Then, in chat: "which CCUs are configured?" (list_ccu_targets), "read the
living-room temperature on dev" (a one-call target: "dev"), "switch to
dev" (use_ccu). With CCU_PROD_PROTECTED=true as above, the first write
against prod comes back asking for confirm: true and unlocks that target for
the rest of the session ā except run_script and delete_system_variable,
which ask every time.
Configuration errors
Some mistakes stop the server at startup instead of being ignored. Each of these
would otherwise fail silently and much later, so the exit is deliberate.
ccu-mcp doctor reports the same errors against an env file without starting
the server, alongside its live checks (reachability, certificate pin, login).
One exception: started with --stdio --env <path>, a failing configuration
enters setup mode (with the error in the
server's instructions) instead of exiting, so it can be fixed conversationally:
Message | Cause and why it's fatal |
| No CCU configured (and no |
| The variable is absent. An empty value is accepted ā a fresh OpenCCU box has no Admin password ā so this means "not set yet", which is what keeps a single-CCU setup-mode server in setup mode until |
| The profile-form equivalent, and setup-mode only: |
| A leftover from a profile setup. Ignoring it would point writes at the flat |
| Empty or comma-only value. |
| Duplicate profile name. |
| Distinct names can collide once sanitised: |
| Typo in the startup profile. |
| Every profile needs a host; the password may be empty. |
| The verification code path only exists over HTTPS. Ignoring these would leave you believing the connection is verified while credentials travel in cleartext. Set |
| Half a TLS config can't serve HTTPS. |
| Case matters. A typo like |
| Ports, timeouts, |
| The two duration settings, |
| Any boolean setting ( |
| Path is wrong or unreadable by the server user. |
ccu-mcp --version and --help work without any configuration, so they stay
usable while you sort one of these out.
Tools
28 tools organized by what you'd actually want to do:
Find things ā list_devices, list_rooms, list_functions, list_interfaces, list_programs, list_system_variables, list_links, describe_device_type
Read state ā get_value, get_values (bulk), get_paramset
Change things ā set_value, put_paramset, set_system_variable, create_system_variable, delete_system_variable, assign_channel, unassign_channel, execute_program
Check health ā get_service_messages, acknowledge_service_messages, get_rssi, get_system_info
Switch targets ā list_ccu_targets, get_connection_info, use_ccu (multi-CCU profiles; see above)
Other ā help (context-aware), run_script (raw HomeMatic Script for bulk operations, renaming devices/channels, querying room membership, or anything not covered by the other tools)
Most tools auto-resolve the interface and value types from the device address ā you don't need to know whether a device is on BidCos-RF or HmIP-RF.
Resources and prompts
Besides tools, the server exposes MCP resources ā browsable JSON snapshots your client can attach as context:
homematic://devices, homematic://rooms, homematic://functions, homematic://programs, homematic://sysvars, homematic://interfaces, homematic://device-types, homematic://system
The server polls the CCU in the background (every RESOURCE_POLL_INTERVAL seconds) and sends notifications/resources/updated for resources whose content changed ā to clients that subscribed to them via resources/subscribe.
It also ships MCP prompts ā ready-made workflows you can invoke from clients that support them (e.g. as slash commands in Claude Code):
check-windowsā are any windows or doors open?room-statusā full status report for one roomset-heatingā set a room's target temperaturegood-nightā prepare the house for nightdiagnosticsā check for device issuesdevice-infoā detailed info about a device's capabilities and parameters
The room and device arguments autocomplete: clients that support
completion/complete offer the rooms and device names this CCU actually has,
so there's no need to remember how a room was spelled in the WebUI.
MCP protocol revisions
The server implements revision 2025-11-25 and negotiates down for older
clients (2025-06-18, 2025-03-26, 2024-11-05 are all accepted) ā you do
not need a particular client version. It advertises tools, resources
(with subscribe), prompts, completions and logging.
Revision 2026-07-28 ā per-request protocol version, server/discover ā is
not implemented yet: the TypeScript SDK this server is built on does not
support it at the time of writing, and this server follows the SDK.
How it works
The server talks to the CCU's JSON-RPC API (the same one the WebUI uses). On startup it:
Logs in and caches the session (reused across restarts)
Loads the device type cache from disk (or warms it in the background)
Starts the MCP server on stdio or HTTP
Device type schemas are cached locally so the AI can look up valid parameters, types, and value ranges without hitting the CCU every time.
Values come back as native types ā 21.5 not "21.500000", true not "true".
Tested devices
This has been tested against a production debmatic installation with:
HmIP-eTRV-2 / eTRV-2 I9F (radiator thermostats)
HmIP-STHD (wall thermostats with humidity)
HmIP-WTH-2 (wall thermostats)
HmIP-SWDO-I (door/window contacts)
HmIP-STHO (outdoor temperature/humidity)
HmIP-ESI (energy/gas meter)
HmIP-FALMOT-C12 (floor heating controller)
HmIP-HEATING (virtual heating groups)
HmIP-WRCC2 (wall remote)
HM-PB-6-WM55 (BidCos 6-button remote)
RPI-RF-MOD (radio module)
Other device types should work too ā the server queries the CCU for parameter descriptions rather than maintaining a static device database.
Changelog
Release notes ā including behavior changes to check before upgrading
(stricter config validation, /health response shape, per-session write
confirmation, retry semantics) ā live in CHANGELOG.md.
Getting help and contributing
Something broken, or an idea for a feature? Open an issue: github.com/claymore666/ccu-mcp/issues
Questions, setup help, general HomeMatic talk? The HomeMatic forum ā the maintainer reads it as
claymore666.Found a security problem? Please don't post it publicly. See SECURITY.md for private reporting.
Want to send a patch? CONTRIBUTING.md covers the setup, the branch to target, the coding standard, and the test policy.
Everyone taking part is expected to follow the Code of Conduct.
Project documentation
Document | What's in it |
Where the project is going ā and what it will deliberately never do | |
Who decides what, and the known continuity gap | |
Reporting, security requirements, threat model | |
High-level design and request flow | |
Why the security requirements hold, with evidence | |
What changed in each release |
Related projects
OpenCCU ā community-maintained, cloud-free CCU firmware for Raspberry Pi, x86/ARM, and CCU3/ELV-Charly hardware (formerly RaspberryMatic; built on the OCCU framework)
debmatic ā Run HomeMatic on Debian, Ubuntu, Raspberry Pi OS, Armbian
OCCU ā eQ-3's original Open CCU SDK (the upstream HomeMatic software); now being superseded by the community-maintained OpenCCU
MCP ā Model Context Protocol specification
ccu-ai-mcp by Mathias (mdzio) ā a kindred MCP server for HomeMatic, taking a deliberately different, elegant approach (a lean Go core with user-defined HM-Script tools). See his write-up on the HomeMatic forum.
License
MIT
Available Tools
28 toolsacknowledge_service_messagesAcknowledge Service MessagesADestructiveIdempotent
Confirm/dismiss active service messages (e.g. clear a low-battery or unreachable warning). Provide an alarm id (from get_service_messages) to confirm one message, or a channel address to confirm all active messages on that channel. A warning reappears if its condition persists.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Alarm id from get_service_messages (confirm a single message) | |
| address | No | Channel address ā confirm all active messages on this channel (e.g. '000A1BE9A71F15:0') | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds behavioral context beyond annotations: warnings reappear if condition persists, and mentions the confirm parameter for protected targets. Annotations already cover idempotence, destructiveness, and open-world.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, no wasted words. Front-loaded with the primary action. Every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, and description does not mention return values (e.g., success indication). Covers key usage and behavior but missing what the agent can expect in response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear descriptions. Description reinforces parameter use but adds little new meaning beyond the schema itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the action (confirm/dismiss) and resource (service messages) with examples. However, it does not explicitly differentiate from siblings like get_service_messages, though the relationship is implied.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides good guidance on using alarm id vs channel address for single vs batch dismissal, and notes that warnings may reappear. Lacks explicit when-not-to-use or alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
assign_channelAssign Channel to Room/FunctionADestructiveIdempotent
Assign a channel to a room and/or a function group. Identify the channel by address and the room/function by name (use list_rooms / list_functions to see names). At least one of room or function is required.
| Name | Required | Description | Default |
|---|---|---|---|
| room | No | Room name (exact match) | |
| channel | Yes | Channel address (e.g. '000A1BE9A71F15:1') | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. | |
| function | No | Function group name (exact match) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint and idempotentHint. The description adds that at least one of room/function is required, but does not elaborate on side effects, reversibility, or the confirm parameter's role in protecting writes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences front-load the core action, then provide lookup guidance and a constraint. No unnecessary words, perfectly sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers core usage and constraints. It omits details about the confirm parameter, behavior when both room and function are provided, and potential overriding of existing assignments. Adequate but not comprehensive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage, the description adds valuable context: how to identify channels by address and rooms/functions by name, and the constraint that at least one of room/function is required. This goes beyond the schema's individual descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool assigns a channel to a room and/or function group, using specific verbs and resources. It distinguishes from sibling tools like unassign_channel and references list_rooms/list_functions for name lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context by noting the requirement of at least one of room or function and suggesting use of list_rooms/list_functions. However, it does not explicitly contrast with alternatives or specify when not to use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_system_variableCreate System VariableADestructive
Create a new system variable. Types: 'bool', 'float' (optional min/max/unit), 'enum' (requires values list), 'string'. Use set_system_variable to write it afterwards, list_system_variables to see existing ones.
| Name | Required | Description | Default |
|---|---|---|---|
| max | No | Maximum value (float only) | |
| min | No | Minimum value (float only) | |
| name | Yes | New variable name (must not already exist) | |
| type | Yes | Variable type | |
| unit | No | Unit label (float only, e.g. '°C') | |
| values | No | Enum value labels in order (enum only, e.g. ['off','low','high']) | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. | |
| description | No | Human-readable description shown in the WebUI |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true. Description adds context about the 'confirm' parameter for protected targets and type constraints, but does not explicitly mention destructive behavior. Acceptable given annotations cover safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with purpose, no redundant words. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a creation tool with 8 parameters and no output schema, description covers type constraints and related tools. Could mention return value, but not required. Fairly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but description adds meaning by explaining type-specific parameter roles (e.g., 'float' optional min/max/unit) and the 'confirm' authorization flag. Goes beyond restating schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Create a new system variable' with a specific verb and resource. Lists types and distinguishes from sibling tools set_system_variable and list_system_variables, providing differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Tells when to use (create a new variable) and gives type-specific guidance (e.g., 'enum requires values list'). References sibling tools for writing and listing. Does not explicitly state when not to use, but schema description implies name must be unique.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_system_variableDelete System VariableADestructiveIdempotent
Delete a system variable by name. Use list_system_variables to see existing names. On a protected target, EVERY call needs confirm:true ā the session unlock from other write tools does not apply.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Variable name (exact match) | |
| confirm | No | Required true on EVERY call against a protected CCU target (e.g. prod) ā deletion never rides on the session unlock. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint and idempotentHint. The description adds crucial context about the confirm parameter requirement on protected targets and clarifies that deletion does not inherit session unlock from other write tools. This goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences. The first immediately states the purpose, the second provides usage guidance. No redundant information, well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple delete tool with two parameters and no output schema, the description covers the main purpose, parameter nuances, and special behavioral requirements. It could mention irreversibility, but annotations already signal destructive nature.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds value: it clarifies that 'name' requires exact match and explains the special behavior of 'confirm' on protected targets. This helps the agent use the parameters correctly beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states 'Delete a system variable by name,' which is a specific verb+resource combination. It clearly distinguishes from sibling tools like create_system_variable and set_system_variable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description advises using list_system_variables to find variable names, which is helpful. It also explains the confirm parameter behavior on protected targets. However, it doesn't mention alternative tools or when not to use deletion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_device_typeDescribe Device TypeARead-only
Get the full channel/datapoint schema for a device type (e.g. 'HmIP-eTRV-2'). Shows all channels, paramsets, datapoint names, types, ranges, and operations. Served from cache (instant). Use list_devices first to find device types.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. | |
| deviceType | Yes | Device type name (e.g. 'HmIP-eTRV-2', 'HmIP-SWDO-I'). Get from list_devices. |
Output Schema
| Name | Required | Description |
|---|---|---|
| deviceType | No | Echoed device type; other keys hold the channel/datapoint schema or a not-found hint |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnly and openWorld hints. Description adds that data is served from cache (instant), which supplements the annotations without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no wasted words. Purpose is front-loaded, usage hint follows efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a simple tool with 2 params, output schema present, and good annotations, the description fully covers purpose, parameters, and usage context. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (baseline 3). Description adds context for both parameters: target references list_ccu_targets and default behavior, deviceType references list_devices, exceeding baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it gets the full channel/datapoint schema for a device type, with specific examples. It doesn't explicitly differentiate from siblings like 'get_paramset', but the unique purpose is evident.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises to use list_devices first to find device types, providing a clear prerequisite. Lacks exclusions or alternative tools, but the guidance is helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
execute_programExecute ProgramADestructive
Trigger an automation program on the CCU. NOT idempotent ā will not be auto-retried. Use list_programs to find program IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Program ID. Get from list_programs. | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (destructiveHint, openWorldHint), the description adds 'NOT idempotent ā will not be auto-retried', which provides critical behavioral context. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is brief (two sentences) and front-loaded with the purpose. It efficiently conveys key points, though the structure could be slightly improved for readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and good annotations, the description provides adequate context. It lacks information about return values or failure behavior, but this is partially mitigated by the annotations and the tool's straightforward nature.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage, the description still adds value by specifying 'Get from list_programs' for the id parameter and explaining the confirm parameter's role for protected targets, enhancing understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Trigger an automation program on the CCU', specifying the verb 'trigger' and the resource 'automation program'. It also distinguishes from siblings by referencing 'list_programs' to obtain program IDs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description indicates non-idempotence and no auto-retry, and directs users to 'list_programs' for IDs. However, it does not explicitly state when to avoid using this tool or mention alternatives among the many sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_connection_infoGet Connection InfoARead-only
Report which CCU target is currently active ā host, user, https, protected/read-only flags, and login state. Use this to confirm WHERE a command will run (especially before a write). No password.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| host | Yes | |
| name | Yes | |
| port | Yes | |
| user | Yes | |
| https | Yes | |
| active | Yes | |
| loggedIn | Yes | |
| readonly | Yes | |
| protected | Yes | |
| writesUnlocked | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint true, so the tool is known safe. The description adds detail on what is reported (host, user, https, flags, login state), enhancing transparency beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with key information. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters, full annotations, and an output schema (implied), the description is complete for a simple informational tool. Covers purpose, usage, and expected output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters; schema coverage is 100%. Baseline of 4 applies as the description need not add parameter info.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool reports which CCU target is active, listing specific fields (host, user, https, flags, login state). It distinguishes from sibling tools by focusing on connection status for confirming where commands will run.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Use this to confirm WHERE a command will run (especially before a write).' Also notes 'No password,' providing clear guidance on when to use and what not to expect.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_paramsetGet ParamsetARead-only
Read all parameters for a channel: VALUES (runtime state), MASTER (config), or a link paramset ā for the latter pass the LINK PARTNER's channel address as paramsetKey (find partners with list_links). Interface is auto-resolved from the address.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. | |
| address | Yes | Channel address (e.g. '000A1BE9A71F15:1') | |
| interface | No | Interface name override (auto-resolved if omitted) | |
| paramsetKey | Yes | 'VALUES', 'MASTER', or a link partner's channel address (reads that direct link's parameters) |
Output Schema
| Name | Required | Description |
|---|---|---|
| params | Yes | Map of parameter name ā value |
| address | Yes | |
| paramsetKey | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description reveals that the tool reads runtime state (VALUES), config (MASTER), or link params, and that interface is auto-resolved. Annotations already declare readOnlyHint=true and openWorldHint=true, so the description adds specific behavioral context without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no wasted words. It front-loads the core purpose and then adds the critical nuance about link paramsets. Every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 4 parameters (2 required), an output schema exists, and annotations are present, the description covers the key aspects: the three paramset types, the special link partner case, and auto-resolution. It is sufficiently complete for an agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (all parameters described), but the description adds extra meaning: it clarifies the paramsetKey values ('VALUES', 'MASTER', or a link partner's address) and confirms the auto-resolution of the interface parameter. This adds value beyond the schema definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a clear verb ('read') and identifies the resource ('parameters for a channel'). It distinguishes three types of paramsets (VALUES, MASTER, link paramset) and explains the special usage for link paramsets via the paramsetKey field. This differentiates it from siblings like put_paramset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by stating what the tool does and mentions using list_links to find partners, but it does not explicitly state when to use this tool versus alternatives (e.g., put_paramset for writing). There is no direct guidance on when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_rssiGet RSSI / Radio QualityARead-only
Report radio link quality (RSSI, in dBm) for every device, resolved to device names, plus BidCos interface health (duty cycle, connected state). Covers both transports: BidCos-RF via Interface.rssiInfo, and HmIP-RF via each device's RSSI_DEVICE/RSSI_PEER maintenance datapoints. Use to answer 'why is this sensor flaky?'. Higher (closer to 0) dBm is better; null = no measurement.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Filter by device name or address (substring, case-insensitive) | |
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| devices | Yes | Per device: {address, name, interface, links:[{peer, rssiDevice, rssiPeer}]} |
| interfaces | Yes | BidCos interface health (duty cycle, connected) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond annotations: explains output includes device names, BidCos interface health (duty cycle, connected state), and null meaning. Adds interpretation guidance: higher dBm is better. No contradictions with readOnlyHint or openWorldHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences pack key information: function, coverage, use case, interpretation. No fluff. Front-loaded with core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given output schema exists, description covers all needed context: purpose, usage scenario, param filter meaning, behavioral details, and value interpretation. Complete for a diagnostic read-only tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear parameter descriptions. The description adds no extra meaning beyond what the schema already provides for the 'name' and 'target' parameters, so baseline score is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb+resource: reports RSSI for all devices. Specifies dBm units and covers both BidCos-RF and HmIP-RF transports. Does not explicitly differentiate from siblings like get_values, but the tool name and description are specific enough to stand out.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a concrete use case: 'Use to answer why is this sensor flaky?' This gives agents clear context for when to invoke. Lacks explicit alternatives or 'when not to use' statements, but the use case is sufficiently directive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_service_messagesGet Service MessagesARead-only
Get all active service messages (low battery, unreachable, etc.) with device details and timestamps.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| messages | Yes | Active alarms: {id, type, address, channelName, timestamp} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true. The description adds behavioral context by specifying it fetches 'active' messages and includes 'device details and timestamps', which goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence of 15 words, front-loaded with the core action 'Get all active service messages', and includes examples and output fields. Every word is purposeful with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema and one optional parameter, the description covers the essential purpose, includes examples, and mentions key output fields. It omits details like pagination or limits, but these may be covered by the output schema. The annotation 'openWorldHint' suggests dynamic results, which the description supports.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description does not add additional meaning for the 'target' parameter; it omits any mention of parameters entirely. The schema itself covers the parameter adequately.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves all active service messages with examples like 'low battery, unreachable' and specifies it includes 'device details and timestamps'. It distinguishes from sibling 'acknowledge_service_messages' by focusing on retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context (retrieving active messages) but does not explicitly state when to use this versus the sibling 'acknowledge_service_messages'. No exclusion criteria or alternative guidance is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_system_infoGet System InfoARead-only
Get CCU system information: firmware version, serial number, addresses. Reports the active login user and inferred role (ADMIN/USER) ā note that version/serial/address are ADMIN-only on the CCU, so they show "N/A" for a non-admin (USER) login. A CCU that cannot be reached or logged into fails with that error instead ā "N/A" always means "connected, not permitted". Also reports the running server's build identification (git branch/commit/tag and build time) under build.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| role | No | Access role inferred from which CCU methods answer: ADMIN if admin-only calls succeed, USER if logged in without admin rights. A CCU that cannot be reached or logged into raises that error instead of reporting a role |
| user | No | Configured login user for the active target |
| build | No | Build identification of the running server (stamped at build time) |
| serial | No | Serial number, or "N/A" if unavailable (ADMIN-only) |
| target | No | Active CCU target name |
| address | No | BidCos address, or "N/A" if unavailable (ADMIN-only) |
| version | No | Firmware version, or "N/A" if unavailable (ADMIN-only) |
| accessNote | No | Present when ADMIN-only fields are unavailable, explaining why |
| cacheTypes | No | |
| hmipAddress | No | HmIP address, or "N/A" if unavailable (ADMIN-only) |
| cacheWarming | No | |
| serverVersion | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, but the description adds valuable behavioral context: ADMIN-only fields show 'N/A' for non-admin users, 'N/A' specifically means connected-but-not-permitted rather than unreachable, and connection/login failures return errors instead. This is exactly the kind of nuance an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and each sentence conveys meaningful operational detail. It is slightly long but justified because of the important 'N/A' vs. error distinction that cannot be safely omitted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description does not need to explain return values. It covers the tool's scope, permission-dependent behavior, and failure semantics, making it complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single optional parameter 'target' is already fully described in the input schema with 100% coverage, including its default and pointer to list_ccu_targets. The description adds no additional parameter semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Get') and resource ('CCU system information'), then enumerates concrete contents: firmware version, serial number, addresses, active login user, role, and build identification. This clearly distinguishes the tool from siblings like get_connection_info and list_interfaces.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes it obvious that this tool reads system information, and the input schema documents the default target. However, it does not explicitly state when to prefer this tool over alternatives like get_connection_info, nor does it give 'when not to use' guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_valueGet ValueARead-only
Read a single datapoint value from a device channel. Only address and valueKey are required ā interface is auto-resolved. Use list_devices to find addresses, describe_device_type to find valid valueKeys.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. | |
| address | Yes | Channel address (e.g. '000A1BE9A71F15:1') | |
| valueKey | Yes | Datapoint name (e.g. 'STATE', 'LEVEL', 'ACTUAL_TEMPERATURE') | |
| interface | No | Interface name override (auto-resolved if omitted) |
Output Schema
| Name | Required | Description |
|---|---|---|
| value | Yes | Parsed datapoint value (bool/number/string/null) |
| address | Yes | |
| valueKey | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and openWorldHint=true. The description reinforces that this is a read operation and adds that the tool reads a single datapoint. It does not contradict annotations and adds context about auto-resolution of interface, which is helpful beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: only two sentences with no unnecessary words. The action ('Read a single datapoint value') is front-loaded, and every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (4 parameters, output schema present), the description is complete. It explains the tool's function, required parameters, and how to find valid inputs. No gaps in information needed for proper use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for all 4 parameters. The description adds value by specifying that only address and valueKey are required and that interface is auto-resolved. It also directs users to other tools for finding valid values, which aids in correct parameter usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Read a single datapoint value from a device channel.' It uses a specific verb (read) and resource (single datapoint value from device channel), and distinguishes from siblings like get_values (plural) and describe_device_type.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use this tool: 'Use list_devices to find addresses, describe_device_type to find valid valueKeys.' It also clarifies that only address and valueKey are required and interface is auto-resolved, providing clear guidance on prerequisites and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_valuesGet Values (Bulk)ARead-only
Read datapoint values for multiple channels at once via HM Script. Provide either a list of channel addresses, or filter by room or function name.
| Name | Required | Description | Default |
|---|---|---|---|
| room | No | Room name ā read all channels in this room | |
| target | No | CCU target to read from (default: active). See list_ccu_targets. | |
| channels | No | Array of channel addresses to read | |
| function | No | Function name ā read all channels in this function group |
Output Schema
| Name | Required | Description |
|---|---|---|
| values | Yes | One entry per channel: {address, name, datapoints} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, which cover safety and external calls. The description adds no additional behavioral context beyond what is in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two efficient sentences front-load the verb and resource, with no wasted words. Every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and clear description of input options (list or filter), the tool is well-documented for its complexity (4 optional params). No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so each parameter has a description. The tool description adds context about the bulk operation and the 'HM Script' method, which adds meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Read datapoint values for multiple channels at once', using a specific verb and resource, and distinguishes from sibling tools like 'get_value' (singular) and 'get_paramset' (different purpose).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides options for input (list of addresses or filter by room/function) but does not give explicit when-to-use or when-not-to-use guidance relative to alternatives. Usage is implied but not fully stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
helpHelpARead-only
Context-aware help. No args: conceptual guide. Tool name (e.g. 'set_value'): tool usage. Device type (e.g. 'HmIP-eTRV-2'): capabilities from cache.
| Name | Required | Description | Default |
|---|---|---|---|
| topic | No | Tool name, device type, or omit for general guide |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate read-only. Description adds that device capabilities come from cache, which is useful beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise: three clauses covering all modes. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Simple tool with one optional param and no output schema. Description covers all usage modes. Missing guidance on invalid topics, but not critical.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema describes parameter 'topic' with same info. Description adds examples but no new semantic meaning beyond schema. Baseline 3 due to high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool provides context-aware help with three modes: no args for conceptual guide, tool name for usage, device type for capabilities. It uses specific verbs and resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage scenarios with examples (no args, tool name, device type). It does not mention when not to use, but the context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_ccu_targetsList CCU TargetsARead-only
List all configured CCU targets (profiles) you can switch between with use_ccu ā name, host, user, whether protected/read-only, which is active, and login state. Never exposes passwords.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| active | Yes | Name of the currently active target |
| targets | Yes | Configured targets: {name, host, port, user, https, protected, readonly, active, loggedIn} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description adds critical safety information: 'Never exposes passwords'. This goes beyond the annotation to assure the agent that sensitive credentials are not leaked.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence that efficiently conveys all necessary information without extraneous words. Purpose is front-loaded and every part of the sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and an output schema present, the description fully explains what the output contains and the tool's role relative to use_ccu. No gaps in information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist in the schema, so the description does not need to elaborate on parameter meaning. Base score of 4 for zero parameters is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it lists CCU targets, specifies exactly what information is included (name, host, user, protected/read-only, active, login state), and distinguishes from the sibling tool use_ccu by noting these are profiles to switch between.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implicitly indicates use before use_ccu by saying 'you can switch between with use_ccu', providing context on when to retrieve this list. However, it does not explicitly state when not to use this tool or mention alternatives beyond use_ccu.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_devicesList DevicesARead-only
List all devices with their channels, types, and addresses. Optional filters: room, function, type, name. Use this first to discover device addresses for get_value/set_value.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Filter by device/channel name (substring, case-insensitive) | |
| room | No | Filter by room name (exact match) | |
| type | No | Filter by device type (exact match, e.g. 'HmIP-eTRV-2') | |
| target | No | CCU target to read from (default: active). See list_ccu_targets. | |
| function | No | Filter by function group name (exact match) |
Output Schema
| Name | Required | Description |
|---|---|---|
| devices | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint true, and the description adds detail on what is returned (channels, types, addresses), providing context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with main purpose, no wasted words. Efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema (exists) and strong annotations, the description covers core functionality. Could mention return format but output schema handles it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents parameters. The description adds a brief summary of filters but no new meaning, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists devices with channels, types, and addresses, and distinguishes it from siblings by mentioning discovery for get_value/set_value.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises using this first to discover addresses for get_value/set_value, but does not specify when not to use it or compare to other listing tools like list_rooms.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_functionsList FunctionsARead-only
List all function groups (Heating, Lighting, etc.) with their assigned channel IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| functions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint. The description adds behavioral context by stating what is listed (all function groups with channel IDs), which aligns with and adds to the annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence with no wasted words. Front-loaded with key information: verb, resource, and output detail. Highly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (1 optional parameter, no nested objects) and presence of an output schema, the description sufficiently covers the tool's purpose and behavior. No missing essential information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameter is already documented. The description adds no extra semantic meaning beyond referencing list_ccu_targets for context. Baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the verb 'List', the specific resource 'function groups', and the output detail 'with their assigned channel IDs'. It distinguishes from sibling tools like list_devices and list_programs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage (listing all function groups) but provides no explicit guidance on when to use this tool versus alternatives. The optional target parameter is mentioned with a reference to list_ccu_targets, but no when-not-to-use or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_interfacesList InterfacesBRead-only
List available communication interfaces (BidCos-RF, HmIP-RF, VirtualDevices, etc.).
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| interfaces | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint and openWorldHint, but the description adds no behavioral context beyond listing example interfaces. It does not disclose any subtleties like what 'available' means (e.g., currently connected or all possible types).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with zero wasted words. It efficiently conveys the tool's purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one optional parameter, output schema exists), the description is largely complete. It could clarify whether the list includes all known interfaces or only currently active ones, but it is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single parameter 'target', with its own description. The tool description does not add extra semantic value for the parameter, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List' and the resource 'communication interfaces', with specific examples (BidCos-RF, HmIP-RF, VirtualDevices). This distinguishes it from sibling tools that list other entities like devices, functions, or rooms.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool versus alternatives like list_devices or list_functions. There is no mention of context, prerequisites, or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_linksList Direct Device LinksARead-only
List direct device links (Direktverknüpfungen) ā senderāreceiver channel pairings that operate independently of the CCU (e.g. a wall switch directly driving a lamp, or thermostats linked to a FALMOT). Read-only. Optionally filter to links involving a specific device or channel address.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. | |
| address | No | Device or channel address to filter by (e.g. '000A1BE9A71F15' or '000A1BE9A71F15:1') |
Output Schema
| Name | Required | Description |
|---|---|---|
| links | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint true and openWorldHint true; the description adds value by explaining that links are senderāreceiver pairings independent of CCU, clarifying the read-only nature and optional filtering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words: first defines the resource with examples, second explains optional filtering. Front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with an output schema and full parameter coverage, the description sufficiently explains the purpose, filtering, and independent nature of links. No gaps noted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with clear parameter descriptions; the description reiterates the address filter but adds no new semantics beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists 'direct device links' with examples (wall switch to lamp, thermostats to FALMOT), distinguishing it from sibling list tools that handle devices, functions, or programs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by defining links as independent of CCU, but does not explicitly state when to prefer this over alternatives or provide when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_programsList ProgramsARead-only
List all automation programs. Use execute_program to trigger them.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Filter by program name (substring, case-insensitive) | |
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| programs | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint. The description adds no further behavioral details beyond listing all programs and the redirection to execute_program, which is adequate but not enhanced.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with the main action, and no wasted words. Ideal structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema, full parameter descriptions in the schema, and annotations covering behavioral aspects, the description sufficiently covers the main action and directs to the relevant sibling for triggering. Slightly more could be said about filtering or target specificity, but it's largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with both parameters described. The description does not add extra meaning beyond the schema, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists all automation programs, using a specific verb and resource. It also distinguishes itself from the sibling tool execute_program by mentioning it for triggering.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides guidance on using execute_program after listing, but lacks broader context on when to use this tool over other list tools (e.g., list_devices, list_functions) among many siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_roomsList RoomsARead-only
List all rooms with their assigned channel IDs. Use with list_devices to find devices by room.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| rooms | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, covering safety and scope. The description adds that it returns channel IDs, but no further behavioral details like ordering or filtering limitations are provided.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with the core purpose, no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the low complexity (one optional parameter, output schema present, annotations rich), the description provides adequate information. Could mention that it returns all rooms without filters, but it's implied by 'list all rooms'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema fully documents the optional 'target' parameter. The description does not add any additional meaning or format details beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('List') and resource ('all rooms'), and specifies the output includes 'assigned channel IDs'. It distinguishes from sibling tools by mentioning usage with list_devices.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear context: 'Use with list_devices to find devices by room'. However, it does not explicitly state when not to use this tool or name specific alternatives, though the sibling context implies it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_system_variablesList System VariablesARead-only
List all system variables with current values and metadata. Use set_system_variable to modify them.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Filter by variable name (substring, case-insensitive) | |
| target | No | CCU target to read from (default: active). See list_ccu_targets. |
Output Schema
| Name | Required | Description |
|---|---|---|
| systemVariables | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the description does not need to add much. It confirms read-only behavior by stating it lists variables, but adds no extra behavioral details beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise: two sentences. The first states the purpose, and the second provides guidance on the alternative. No unnecessary information, perfectly front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (listing with optional filters) and the presence of an output schema, the description is complete. It covers purpose, alternative tool, and parameters are well-documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers both parameters with descriptions, achieving 100% coverage. The tool description does not add additional meaning beyond what the schema provides, warranting a baseline score of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists all system variables with current values and metadata. It distinguishes itself from sibling tools by indicating that modification should be done via set_system_variable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells agents to use set_system_variable for modifications, providing clear guidance on when not to use this tool. However, it does not mention other siblings like create or delete, slightly reducing completeness.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
put_paramsetPut ParamsetADestructiveIdempotent
Write multiple parameters at once (e.g. thermostat weekly profile). Interface is auto-resolved from address.
| Name | Required | Description | Default |
|---|---|---|---|
| set | Yes | Key-value pairs to write (e.g. {TEMPERATURE_WINDOW_OPEN: 5.0}) | |
| address | Yes | Channel address | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. | |
| interface | No | Interface name override | |
| paramsetKey | Yes | Paramset to write |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With destructiveHint and idempotentHint already annotated, the description need not restate safety. It adds one useful behavior (interface auto-resolution from address), but does not describe write effects on existing values or the confirm/protected-target flow, leaving some behavioral context to the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The main action and an example come first, followed by the interface behavior; every clause contributes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich 100%-covered schema and the destructive/idempotent annotations, the description plus schema are sufficient to invoke the tool correctly for common cases. It lacks an explicit alternative routing and return-value note, but these are minor for this write tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds a small amount (interface auto-resolution and an example for set), but most parameter meaning is already in the schema; it does not materially compensate for any gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Write'), resource ('multiple parameters'/paramset), and provides a concrete example (thermostat weekly profile). This clearly distinguishes it from siblings like set_value (single-value write) and get_paramset (read).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Write multiple parameters at once' gives clear context for when to use this tool instead of a single-value write, and the example adds a realistic use case. It does not explicitly name alternatives or exclusions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_scriptRun HomeMatic ScriptADestructive
Execute arbitrary HomeMatic Script on the CCU. NOT idempotent ā will not be auto-retried. Use for anything the other tools don't cover. On a protected target, EVERY call needs confirm:true ā the session unlock from other write tools does not apply.
| Name | Required | Description | Default |
|---|---|---|---|
| script | Yes | HomeMatic Script to execute | |
| confirm | No | Required true on EVERY call against a protected CCU target (e.g. prod) ā scripts never ride on the session unlock. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (openWorldHint, destructiveHint), the description adds key behavioral traits: not idempotent, not auto-retried, and the separate confirm requirement for protected targets. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each adding unique value with no wasted words. Front-loaded with purpose, followed by critical behavioral and usage notes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool executing arbitrary scripts, the description covers safety (idempotency, confirm), usage scope, and distinguishes from siblings. No output schema exists, but return values are inherently unpredictable, so this is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, providing baseline of 3. The description adds meaningful extra context for 'confirm' parameter, explaining why it must be true on every call for protected targets, which is valuable beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Execute arbitrary HomeMatic Script on the CCU' with a specific verb and resource. It distinguishes from siblings by stating it's for anything other tools don't cover.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-not (not idempotent, not auto-retried) and specifies that on protected targets every call needs confirm:true, with rationale about session unlock not applying. This gives clear guidance on when and how to use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_system_variableSet System VariableADestructiveIdempotent
Set a system variable value. Type is auto-detected ā use list_system_variables to see available variables.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Variable name (exact match) | |
| value | Yes | Value to set | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare the operation destructive, idempotent, and open-world. The description adds one behavioral detail beyond that: type auto-detection. It does not mention overwrite semantics or the protected-target confirmation behavior, though the confirm parameter schema covers that context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence that states the operation and immediately provides the most useful usage hint. There is no redundant repetition of schema information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive write with a confirmation parameter, the description is somewhat thin: it relies on the schema for protected-target behavior and does not clarify when to use it versus set_value or put_paramset. Still, annotations and a fully described schema make the tool callable without fatal gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds value: 'use list_system_variables to see available variables' helps supply a dynamic value for the name parameter, and 'Type is auto-detected' clarifies how the value union is interpreted. The confirm parameter is already well described in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Set') and resource ('a system variable value'), distinguishing it from create_system_variable and delete_system_variable. However, it does not explicitly state that it modifies an existing variable or differentiate it from the sibling set_value tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives one useful routing cue: 'use list_system_variables to see available variables' for discovering valid names. It does not say when to prefer this tool over set_value or put_paramset, nor does it give an explicit when-not-to-use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_valueSet ValueADestructiveIdempotent
Set a single datapoint value on a device channel. Only address, valueKey, and value are required ā interface and type are auto-resolved. Returns the previous value for undo. Use describe_device_type to find valid valueKeys and ranges.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Value type override (auto-resolved if omitted) | |
| value | Yes | Value to set | |
| address | Yes | Channel address (e.g. '000A1BE9A71F15:1') | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. | |
| valueKey | Yes | Datapoint name (e.g. 'STATE', 'LEVEL', 'SET_POINT_TEMPERATURE') | |
| interface | No | Interface name override (auto-resolved if omitted) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With destructiveHint=true already signaling a write/overwrite, the description adds behavioral context by stating that interface and type are auto-resolved and that the previous value is returned for undo. This is valuable beyond annotations because it tells agents how to recover from the mutation. No contradiction with openWorldHint or idempotentHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each carrying distinct information: purpose, required parameter set, undo behavior, and validation guidance. It is front-loaded with the operation and does not waste words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core action, required inputs, auto-resolution behavior, return value, and where to look up valid valueKeys. The confirm parameter's protected-target behavior is fully documented in the schema, so its absence here is acceptable. There is no output schema, but the return value is stated clearly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
While the schema describes all six parameters (100% coverage), the description adds semantic value by emphasizing that only address, valueKey, and value are required and that interface/type need not be supplied because they are auto-resolved. This prevents an agent from over-specifying parameters. It also ties valueKey to valid values via describe_device_type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Set a single datapoint value on a device channel.' It clarifies the unique scope ('single datapoint') and distinguishes itself from sibling tools like set_system_variable or put_paramset by targeting a device channel datapoint. The mention of auto-resolution and undo further identifies its specific behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The statement 'Only address, valueKey, and value are required' gives clear prerequisites, and 'Use describe_device_type to find valid valueKeys and ranges' explicitly routes users to a sibling for pre-validation. It does not mention when not to use this tool, but the intended contextāsetting a single datapointāis clear enough to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unassign_channelRemove Channel from Room/FunctionADestructiveIdempotent
Remove a channel from a room and/or a function group. Identify the channel by address and the room/function by name (use list_rooms / list_functions to see names). At least one of room or function is required.
| Name | Required | Description | Default |
|---|---|---|---|
| room | No | Room name (exact match) | |
| channel | Yes | Channel address (e.g. '000A1BE9A71F15:1') | |
| confirm | No | Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session. | |
| function | No | Function group name (exact match) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint: true, but the description adds value by explaining the confirm parameter's role for protected targets and that it unlocks writes for the session. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core purpose, and every word adds value. No redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 4 parameters, no output schema, and moderate complexity, the description covers the main aspects: what it does, how to specify entities, the constraint on room/function, and the confirm parameter. It could mention idempotency (annotations say idempotentHint: true) but is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already has 100% description coverage for parameters, the description adds critical usage semantics: the mutual requirement of at least one of 'room' or 'function', and how to obtain valid names using list_rooms/list_functions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action 'Remove a channel' and the target resource 'room and/or a function group'. It distinguishes from the sibling tool 'assign_channel' which performs the inverse operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on how to identify the channel (by address) and the room/function (by name, referencing list_rooms/list_functions). It also states that at least one of room or function is required, though it does not explicitly mention when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
use_ccuSwitch CCU TargetA
Switch the active CCU target. All subsequent tool calls go to this target until switched again (use the per-call target arg on read tools for a one-off without switching). Returns the new active connection info. Login happens lazily on the first call.
| Name | Required | Description | Default |
|---|---|---|---|
| profile | Yes | Target name (see list_ccu_targets) |
Output Schema
| Name | Required | Description |
|---|---|---|
| host | Yes | |
| name | Yes | |
| port | Yes | |
| user | Yes | |
| https | Yes | |
| active | Yes | |
| loggedIn | Yes | |
| readonly | Yes | |
| protected | Yes | |
| writesUnlocked | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses stateful behavior ('all subsequent tool calls go to this target'), lazy login, and return value. Annotations only indicate non-read-only, so the description adds essential behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (three sentences) and well-structured: first sentence states the action, second explains persistence and alternative, third covers return and login. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers switching behavior, alternative usage, return info, and lazy login. It references sibling tool `list_ccu_targets` for valid profiles. Given an output schema is present, return value details are not needed. Context is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter 'profile' has a description that references `list_ccu_targets` for valid values, adding meaning beyond the type string. Schema coverage is 100%, baseline 3, but the hint elevates it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to switch the active CCU target. It uses a specific verb ('Switch') and resource ('CCU target'), and distinguishes from the per-call `target` argument alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly specifies when to use this tool (to switch the active target) and when not (for a one-off, use per-call `target` arg). It provides an alternative, making usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v1.11.0- Changed
get_system_info13 fields changed- removed
Output schema / properties / build / properties / branch / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / build / properties / branch / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / build / properties / builtAt / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / build / properties / builtAt / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / build / properties / commit / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / build / properties / commit / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / build / properties / describe / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / build / properties / describe / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / build / properties / dirty / anyOfRemoved value: -[ - { - "type": "boolean" - }, - { - "type": "null" - } -] - added
Output schema / properties / build / properties / dirty / typeAdded value: +[ + "boolean", + "null" +] - removed
Output schema / properties / build / properties / tag / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / build / properties / tag / typeAdded value: +[ + "string", + "null" +] - changed
Output schema / properties / role / descriptionPrevious value: -"Access role inferred from which CCU methods answer: ADMIN if admin-only calls succeed, USER if logged in without admin rights, UNKNOWN if not connected"New value: +"Access role inferred from which CCU methods answer: ADMIN if admin-only calls succeed, USER if logged in without admin rights. A CCU that cannot be reached or logged into raises that error instead of reporting a role"
- Changed
put_paramset2 fields changed- removed
Input schema / properties / set / additionalProperties / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } -] - added
Input schema / properties / set / additionalProperties / typeAdded value: +[ + "string", + "number", + "boolean" +]
- Changed
set_system_variable2 fields changed- removed
Input schema / properties / value / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } -] - added
Input schema / properties / value / typeAdded value: +[ + "string", + "number", + "boolean" +]
- Changed
set_value2 fields changed- removed
Input schema / properties / value / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - } -] - added
Input schema / properties / value / typeAdded value: +[ + "string", + "number", + "boolean" +]
1 tool update
v1.8.0- Changed
acknowledge_service_messages1 field changed- changed
Input schema / properties / confirm / descriptionPrevious value: -"Set true to authorize this write against a protected CCU target (e.g. prod)."New value: +"Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session."
27 tool updates
v1.7.0- Changed
acknowledge_service_messages1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod).", + "type": "boolean" +}
- Changed
assign_channel1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.", + "type": "boolean" +}
- Changed
create_system_variable1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.", + "type": "boolean" +}
- Changed
delete_system_variable1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Required true on EVERY call against a protected CCU target (e.g. prod) ā deletion never rides on the session unlock.", + "type": "boolean" +}
- Changed
describe_device_type1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
execute_program1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.", + "type": "boolean" +}
- Added
get_connection_info - Changed
get_paramset3 fields changed- changed
Input schema / properties / paramsetKey / descriptionPrevious value: -"Paramset to read"New value: +"'VALUES', 'MASTER', or a link partner's channel address (reads that direct link's parameters)" - removed
Input schema / properties / paramsetKey / enumRemoved value: -[ - "VALUES", - "MASTER", - "LINK" -] - added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
get_rssi1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
get_service_messages2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
get_system_info11 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +} - added
Output schema / properties / accessNoteAdded value: +{ + "description": "Present when ADMIN-only fields are unavailable, explaining why", + "type": "string" +} - added
Output schema / properties / address / descriptionAdded value: +"BidCos address, or \"N/A\" if unavailable (ADMIN-only)" - added
Output schema / properties / buildAdded value: +{ + "additionalProperties": false, + "description": "Build identification of the running server (stamped at build time)", + "properties": { + "branch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Git branch (null if detached or not a git checkout)" + }, + "builtAt": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "ISO timestamp of the build" + }, + "commit": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Short commit SHA" + }, + "describe": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "git describe --tags --dirty --always" + }, + "dirty": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "true if the working tree had uncommitted changes at build time" + }, + "tag": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Tag if HEAD is exactly on one, else null" + } + }, + "required": [ + "branch", + "commit", + "tag", + "describe", + "dirty", + "builtAt" + ], + "type": "object" +} - added
Output schema / properties / hmipAddress / descriptionAdded value: +"HmIP address, or \"N/A\" if unavailable (ADMIN-only)" - added
Output schema / properties / roleAdded value: +{ + "description": "Access role inferred from which CCU methods answer: ADMIN if admin-only calls succeed, USER if logged in without admin rights, UNKNOWN if not connected", + "enum": [ + "ADMIN", + "USER", + "UNKNOWN" + ], + "type": "string" +} - added
Output schema / properties / serial / descriptionAdded value: +"Serial number, or \"N/A\" if unavailable (ADMIN-only)" - added
Output schema / properties / targetAdded value: +{ + "description": "Active CCU target name", + "type": "string" +} - added
Output schema / properties / userAdded value: +{ + "description": "Configured login user for the active target", + "type": "string" +} - added
Output schema / properties / version / descriptionAdded value: +"Firmware version, or \"N/A\" if unavailable (ADMIN-only)"
- Changed
get_value1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
get_values1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Added
list_ccu_targets - Changed
list_devices1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
list_functions2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
list_interfaces2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
list_links1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
list_programs1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
list_rooms2 fields changed- added
Input schema / $schemaAdded value: +"http://json-schema.org/draft-07/schema#" - added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
list_system_variables1 field changed- added
Input schema / properties / targetAdded value: +{ + "description": "CCU target to read from (default: active). See list_ccu_targets.", + "type": "string" +}
- Changed
put_paramset1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.", + "type": "boolean" +}
- Changed
run_script1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Required true on EVERY call against a protected CCU target (e.g. prod) ā scripts never ride on the session unlock.", + "type": "boolean" +}
- Changed
set_system_variable1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.", + "type": "boolean" +}
- Changed
set_value1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.", + "type": "boolean" +}
- Changed
unassign_channel1 field changed- added
Input schema / properties / confirmAdded value: +{ + "description": "Set true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.", + "type": "boolean" +}
- Added
use_ccu
19 tool updates
v1.3.0- Added
acknowledge_service_messages - Added
assign_channel - Added
create_system_variable - Added
delete_system_variable - Changed
describe_device_type1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "deviceType": { + "description": "Echoed device type; other keys hold the channel/datapoint schema or a not-found hint", + "type": "string" + } + }, + "type": "object" +}
- Changed
get_paramset1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "address": { + "type": "string" + }, + "params": { + "description": "Map of parameter name ā value" + }, + "paramsetKey": { + "type": "string" + } + }, + "required": [ + "address", + "paramsetKey", + "params" + ], + "type": "object" +}
- Added
get_rssi - Changed
get_service_messages1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "messages": { + "description": "Active alarms: {id, type, address, channelName, timestamp}", + "items": {}, + "type": "array" + } + }, + "required": [ + "messages" + ], + "type": "object" +}
- Changed
get_system_info1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "address": {}, + "cacheTypes": { + "type": "number" + }, + "cacheWarming": { + "type": "boolean" + }, + "hmipAddress": {}, + "serial": {}, + "serverVersion": { + "type": "string" + }, + "version": {} + }, + "type": "object" +}
- Changed
get_value1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "address": { + "type": "string" + }, + "value": { + "description": "Parsed datapoint value (bool/number/string/null)" + }, + "valueKey": { + "type": "string" + } + }, + "required": [ + "address", + "valueKey", + "value" + ], + "type": "object" +}
- Changed
get_values1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "values": { + "description": "One entry per channel: {address, name, datapoints}", + "items": {}, + "type": "array" + } + }, + "required": [ + "values" + ], + "type": "object" +}
- Changed
list_devices1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "devices": { + "items": {}, + "type": "array" + } + }, + "required": [ + "devices" + ], + "type": "object" +}
- Changed
list_functions1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "functions": { + "items": {}, + "type": "array" + } + }, + "required": [ + "functions" + ], + "type": "object" +}
- Changed
list_interfaces1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "interfaces": { + "items": {}, + "type": "array" + } + }, + "required": [ + "interfaces" + ], + "type": "object" +}
- Added
list_links - Changed
list_programs1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "programs": { + "items": {}, + "type": "array" + } + }, + "required": [ + "programs" + ], + "type": "object" +}
- Changed
list_rooms1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "rooms": { + "items": {}, + "type": "array" + } + }, + "required": [ + "rooms" + ], + "type": "object" +}
- Changed
list_system_variables1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "systemVariables": { + "items": {}, + "type": "array" + } + }, + "required": [ + "systemVariables" + ], + "type": "object" +}
- Added
unassign_channel
18 tool updates
v1.1.2- First observed
describe_device_type - First observed
execute_program - First observed
get_paramset - First observed
get_service_messages - First observed
get_system_info - First observed
get_value - First observed
get_values - First observed
help - First observed
list_devices - First observed
list_functions - First observed
list_interfaces - First observed
list_programs - First observed
list_rooms - First observed
list_system_variables - First observed
put_paramset - First observed
run_script - First observed
set_system_variable - First observed
set_value
TDQS
Scored across 28 tools
Tools are cleanly organized by resource type (devices, system variables, programs, rooms, CCU targets), so most purposes are unmistakable. Mild ambiguity exists between get_value/get_values, set_value/put_paramset, and execute_program/run_script, though the descriptions do draw clear lines between them.
Every tool follows a consistent verb_noun snake_case convention, with tidy prefixes: list_* for enumeration, get_* for reads, set_/put_/create_/delete_ for writes, and precise action verbs (assign, execute, acknowledge, use). Even put_paramset vs set_value maps to a meaningful full-resource vs single-datapoint distinction.
28 tools is above the typical ideal range, but the server covers an unusually broad domain: device I/O, paramsets, system variables, programs, rooms/functions, links, service messages, RSSI diagnostics, and multi-CCU target management. There is little redundancy ā apparent duplicates like get_value/get_values and get_connection_info/list_ccu_targets are justified single-vs-batch or detail-vs-list splits.
Core lifecycles are covered well: system variables have full list/set/create/delete, channels have single and bulk read/write, rooms and functions have assign/unassign, and service messages have get/acknowledge. Notable gaps are program creation/editing and link creation/deletion (list_links is explicitly read-only), but run_script provides a documented universal escape hatch that mitigates most dead ends.
Maintenance
Related MCP Connectors
MCP connector that lets ChatGPT list, search, and run your Apple Shortcuts via a local Mac agent
Personal assistant MCP server with search, execute, packages, jobs, secrets, and integrations.
Related MCP Servers
- FlicenseBqualityNot gradedmaintenanceEnables control and monitoring of Home Assistant smart home devices through MCP, allowing users to list entities, check device states, and call services to control lights, switches, sensors, and other connected devices.4-
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to control Home Assistant smart home devices via MCP, with zero external dependencies. Supports calling services, getting states, and looking up service parameters.38MIT
- AlicenseNot gradedqualityCmaintenanceEnables natural language control of Loxone smart home systems, including lighting, audio, climate, and environmental monitoring, through MCP-compatible clients.102AGPL 3.0
- FlicenseNot gradedqualityFmaintenanceEnables AI assistants to control and query smart home devices through Homey Pro via an HTTP-based MCP server.2-