Skip to main content
Glama
claymore666

debmatic-mcp

by claymore666

OpenSSF Best Practices OpenSSF Scorecard

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 --stdio

If 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 --stdio

Option 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:latest

Every 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_HOSTS is required for remote clients. The server's DNS-rebinding protection rejects any request whose Host header isn't on the allowlist — by default only localhost/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/.env

This 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.json

This only updates the ccu-mcp entry — other servers in your .mcp.json are left alone.

4. Check it's healthy:

curl http://localhost:3000/health

Browser-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 for MCP_AUTH_TOKEN_GRACE_HOURS (default 24) so in-flight clients survive the swap. To force a rotation sooner, delete $CACHE_DIR/.env (or just its MCP_AUTH_TOKEN line) and restart.

  • Explicit token — when you set MCP_AUTH_TOKEN yourself, you own its lifetime (TTL doesn't apply). To rotate, put the new token in MCP_AUTH_TOKEN, move the old one to MCP_AUTH_TOKEN_PREVIOUS, and restart; both are accepted during the overlap. Drop MCP_AUTH_TOKEN_PREVIOUS and 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=443

The 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_FINGERPRINT to 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 -sha256
  • Trust a CA/self-signed PEM: point CCU_CA_CERT at 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

CCU_HOST

required

Hostname or IP of your CCU

CCU_PASSWORD

required

CCU admin password. Must be set, but may be empty for a box without one (a fresh OpenCCU)

CCU_USER

Admin

CCU username

CCU_PORT

80

API port (443 when using HTTPS)

CCU_HTTPS

false

Connect via HTTPS (self-signed certs supported)

CCU_TLS_VERIFY

false

Verify the CCU's TLS certificate against the system trust store (for a publicly-trusted cert)

CCU_TLS_FINGERPRINT

unset

Pin the CCU's self-signed leaf cert by its SHA-256 fingerprint (hex, colons optional). Takes precedence over the other TLS options

CCU_CA_CERT

unset

Path to the CCU's CA/self-signed PEM for chain validation

CCU_TIMEOUT

10000

CCU request timeout in milliseconds

CCU_SCRIPT_TIMEOUT

30000

HM Script execution timeout in milliseconds

LOG_LEVEL

info

error, warn, info, or debug

CACHE_DIR

/data

Where to store device type cache and session

CACHE_TTL

86400

Cache lifetime in seconds (24h)

MCP_TRANSPORT

http

http or stdio (the --stdio CLI flag overrides this)

MCP_PORT

3000

HTTP server port (HTTP mode only)

MCP_AUTH_TOKEN

auto-generated

Bearer token for HTTP mode; generated and saved to $CACHE_DIR/.env on first start

MCP_AUTH_TOKEN_PREVIOUS

unset

Previous bearer token, accepted alongside MCP_AUTH_TOKEN during a rotation overlap; remove it (and restart) to end the overlap. Explicit-token path only

MCP_AUTH_TOKEN_TTL_DAYS

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 MCP_AUTH_TOKEN is set

MCP_AUTH_TOKEN_GRACE_HOURS

24

Overlap (hours) after an auto-rotation during which the just-replaced token is still accepted

MCP_ALLOWED_ORIGINS

unset

Comma-separated allowlist of browser origins. Unset = no cross-origin browser access (default-deny). An allowlisted origin is reflected exactly in Access-Control-Allow-Origin (never *); the list also drives DNS-rebinding origin checks

MCP_ALLOWED_HOSTS

localhost/127.0.0.1/[::1] on the MCP port

Extra Host values accepted by DNS-rebinding protection (comma-separated host:port); add every name/IP clients use to reach the server (proxy, container DNS name, plain server IP)

MCP_HOST

unset (all interfaces)

Bind address for the HTTP listener; set 127.0.0.1 to restrict to loopback (e.g. behind a TLS-terminating proxy), which also silences the plaintext warning

MCP_TLS_CERT / MCP_TLS_KEY

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

MCP_ALLOW_PLAINTEXT

false

Set true to acknowledge serving the bearer token over plain HTTP and silence the non-loopback plaintext warning

CCU_RATE_LIMIT_BURST

20

Max burst of requests sent to the CCU

CCU_RATE_LIMIT_RATE

10

Sustained CCU requests per second

RESOURCE_POLL_INTERVAL

60

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 exit

ccu-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.0

Note 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 — the env block shown in Option A above. Simplest; self-contained.

  • Shell export — as in Quick start above.

  • A .env file — keeps secrets out of .mcp.json. Pass it with the server's own --env flag (this is also what ccu-mcp init writes 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 to dist/index.js.)

    Copy .env.example to .env and fill it in (it documents every variable). Docker users can pass the same file with docker run --env-file .env or compose's env_file:. Keep .env gitignored.

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 with confirm: true, which unlocks writes to that target for the rest of the session. Exception: run_script and delete_system_variable require confirm: true on 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

CCU_HOST environment variable is required

No CCU configured (and no CCU_PROFILES).

CCU_PASSWORD environment variable is required

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 ccu-mcp secret stores one.

no password stored yet for target <name>

The profile-form equivalent, and setup-mode only: CCU_<NAME>_PASSWORD is absent. A loaded configuration still reads an absent key as empty (unchanged, so an OpenCCU dev target keeps working) — but for deciding whether setup is finished, absent means "not entered yet", so the server stays in setup mode and prints the ccu-mcp secret <name> run that completes it. Write CCU_<NAME>_PASSWORD= to declare an empty password deliberate.

CCU_DEFAULT_PROFILE is set but CCU_PROFILES is not

A leftover from a profile setup. Ignoring it would point writes at the flat CCU_HOST box while the env file suggests a named target.

CCU_PROFILES is set but lists no profile names

Empty or comma-only value.

CCU_PROFILES lists "<name>" more than once

Duplicate profile name.

... both map to the same env prefix CCU_<P>_* — rename one

Distinct names can collide once sanitised: prod-a and prod.a both read CCU_PROD_A_*, so they would silently be the same target.

CCU_DEFAULT_PROFILE="x" is not one of CCU_PROFILES (...)

Typo in the startup profile.

profile "<name>" is missing CCU_<P>_HOST

Every profile needs a host; the password may be empty.

TLS_FINGERPRINT/CA_CERT/TLS_VERIFY is set but HTTPS is disabled

The verification code path only exists over HTTPS. Ignoring these would leave you believing the connection is verified while credentials travel in cleartext. Set CCU_HTTPS=true (or CCU_<NAME>_HTTPS=true) or remove them.

MCP_TLS_CERT and MCP_TLS_KEY must both be set (or both unset)

Half a TLS config can't serve HTTPS.

MCP_TRANSPORT must be "http" or "stdio"

Case matters. A typo like STDIO must not silently select HTTP and leave a stdio-spawning client waiting forever.

<VAR> must be a positive integer

Ports, timeouts, CACHE_TTL, rate limits, RESOURCE_POLL_INTERVAL. The whole value has to be digits — CCU_TIMEOUT=30s is rejected rather than read as 30 ms, and 30.5 or 1e4 are rejected rather than truncated.

<VAR> must be a positive number

The two duration settings, MCP_AUTH_TOKEN_TTL_DAYS and MCP_AUTH_TOKEN_GRACE_HOURS, where a fractional value is meaningful.

<VAR> must be "true" or "false"

Any boolean setting (CCU_HTTPS, CCU_TLS_VERIFY, CCU_<NAME>_PROTECTED, CCU_<NAME>_READONLY, MCP_ALLOW_PLAINTEXT). Surrounding whitespace and capitalisation are fine; yes, 1 and on are not, because treating them as false would quietly switch a protection off.

CCU_CA_CERT could not be read

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 room

  • set-heating — set a room's target temperature

  • good-night — prepare the house for night

  • diagnostics — check for device issues

  • device-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:

  1. Logs in and caches the session (reused across restarts)

  2. Loads the device type cache from disk (or warms it in the background)

  3. 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

ROADMAP.md

Where the project is going — and what it will deliberately never do

GOVERNANCE.md

Who decides what, and the known continuity gap

SECURITY.md

Reporting, security requirements, threat model

docs/architecture.md

High-level design and request flow

docs/assurance-case.md

Why the security requirements hold, with evidence

CHANGELOG.md

What changed in each release

  • 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 tools
acknowledge_service_messagesAcknowledge Service MessagesA
DestructiveIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAlarm id from get_service_messages (confirm a single message)
addressNoChannel address — confirm all active messages on this channel (e.g. '000A1BE9A71F15:0')
confirmNoSet 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

A3.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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/FunctionA
DestructiveIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
roomNoRoom name (exact match)
channelYesChannel address (e.g. '000A1BE9A71F15:1')
confirmNoSet true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.
functionNoFunction group name (exact match)

TDQS

A4.1/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 VariableA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxNoMaximum value (float only)
minNoMinimum value (float only)
nameYesNew variable name (must not already exist)
typeYesVariable type
unitNoUnit label (float only, e.g. '°C')
valuesNoEnum value labels in order (enum only, e.g. ['off','low','high'])
confirmNoSet true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.
descriptionNoHuman-readable description shown in the WebUI

TDQS

A4.2/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 VariableA
DestructiveIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesVariable name (exact match)
confirmNoRequired true on EVERY call against a protected CCU target (e.g. prod) — deletion never rides on the session unlock.

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 TypeA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.
deviceTypeYesDevice type name (e.g. 'HmIP-eTRV-2', 'HmIP-SWDO-I'). Get from list_devices.

Output Schema

ParametersJSON Schema
NameRequiredDescription
deviceTypeNoEchoed device type; other keys hold the channel/datapoint schema or a not-found hint

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 ProgramA
Destructive

Trigger an automation program on the CCU. NOT idempotent — will not be auto-retried. Use list_programs to find program IDs.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesProgram ID. Get from list_programs.
confirmNoSet 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

A4.6/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness4/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 InfoA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
hostYes
nameYes
portYes
userYes
httpsYes
activeYes
loggedInYes
readonlyYes
protectedYes
writesUnlockedYes

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 ParamsetA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.
addressYesChannel address (e.g. '000A1BE9A71F15:1')
interfaceNoInterface name override (auto-resolved if omitted)
paramsetKeyYes'VALUES', 'MASTER', or a link partner's channel address (reads that direct link's parameters)

Output Schema

ParametersJSON Schema
NameRequiredDescription
paramsYesMap of parameter name → value
addressYes
paramsetKeyYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 QualityA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoFilter by device name or address (substring, case-insensitive)
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
devicesYesPer device: {address, name, interface, links:[{peer, rssiDevice, rssiPeer}]}
interfacesYesBidCos interface health (duty cycle, connected)

TDQS

A4.3/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose4/5

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.

Usage Guidelines4/5

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 MessagesA
Read-only

Get all active service messages (low battery, unreachable, etc.) with device details and timestamps.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messagesYesActive alarms: {id, type, address, channelName, timestamp}

TDQS

A4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 InfoA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
roleNoAccess 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
userNoConfigured login user for the active target
buildNoBuild identification of the running server (stamped at build time)
serialNoSerial number, or "N/A" if unavailable (ADMIN-only)
targetNoActive CCU target name
addressNoBidCos address, or "N/A" if unavailable (ADMIN-only)
versionNoFirmware version, or "N/A" if unavailable (ADMIN-only)
accessNoteNoPresent when ADMIN-only fields are unavailable, explaining why
cacheTypesNo
hmipAddressNoHmIP address, or "N/A" if unavailable (ADMIN-only)
cacheWarmingNo
serverVersionNo

TDQS

A4.2/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 ValueA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.
addressYesChannel address (e.g. '000A1BE9A71F15:1')
valueKeyYesDatapoint name (e.g. 'STATE', 'LEVEL', 'ACTUAL_TEMPERATURE')
interfaceNoInterface name override (auto-resolved if omitted)

Output Schema

ParametersJSON Schema
NameRequiredDescription
valueYesParsed datapoint value (bool/number/string/null)
addressYes
valueKeyYes

TDQS

A4.7/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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)A
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
roomNoRoom name — read all channels in this room
targetNoCCU target to read from (default: active). See list_ccu_targets.
channelsNoArray of channel addresses to read
functionNoFunction name — read all channels in this function group

Output Schema

ParametersJSON Schema
NameRequiredDescription
valuesYesOne entry per channel: {address, name, datapoints}

TDQS

A4.1/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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.

helpHelpA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
topicNoTool name, device type, or omit for general guide

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 TargetsA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
activeYesName of the currently active target
targetsYesConfigured targets: {name, host, port, user, https, protected, readonly, active, loggedIn}

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 DevicesA
Read-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.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoFilter by device/channel name (substring, case-insensitive)
roomNoFilter by room name (exact match)
typeNoFilter by device type (exact match, e.g. 'HmIP-eTRV-2')
targetNoCCU target to read from (default: active). See list_ccu_targets.
functionNoFilter by function group name (exact match)

Output Schema

ParametersJSON Schema
NameRequiredDescription
devicesYes

TDQS

A4.2/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 FunctionsA
Read-only

List all function groups (Heating, Lighting, etc.) with their assigned channel IDs.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
functionsYes

TDQS

A4.1/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 InterfacesB
Read-only

List available communication interfaces (BidCos-RF, HmIP-RF, VirtualDevices, etc.).

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
interfacesYes

TDQS

B3.4/5.0
Behavior2/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines2/5

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_programsList ProgramsA
Read-only

List all automation programs. Use execute_program to trigger them.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoFilter by program name (substring, case-insensitive)
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
programsYes

TDQS

A3.8/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines3/5

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 RoomsA
Read-only

List all rooms with their assigned channel IDs. Use with list_devices to find devices by room.

ParametersJSON Schema
NameRequiredDescriptionDefault
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
roomsYes

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 VariablesA
Read-only

List all system variables with current values and metadata. Use set_system_variable to modify them.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoFilter by variable name (substring, case-insensitive)
targetNoCCU target to read from (default: active). See list_ccu_targets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
systemVariablesYes

TDQS

A4.1/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 ParamsetA
DestructiveIdempotent

Write multiple parameters at once (e.g. thermostat weekly profile). Interface is auto-resolved from address.

ParametersJSON Schema
NameRequiredDescriptionDefault
setYesKey-value pairs to write (e.g. {TEMPERATURE_WINDOW_OPEN: 5.0})
addressYesChannel address
confirmNoSet true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.
interfaceNoInterface name override
paramsetKeyYesParamset to write

TDQS

A4/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters3/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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 ScriptA
Destructive

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
scriptYesHomeMatic Script to execute
confirmNoRequired true on EVERY call against a protected CCU target (e.g. prod) — scripts never ride on the session unlock.

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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 VariableA
DestructiveIdempotent

Set a system variable value. Type is auto-detected — use list_system_variables to see available variables.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesVariable name (exact match)
valueYesValue to set
confirmNoSet 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

A3.6/5.0
Behavior3/5

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.

Conciseness5/5

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.

Completeness3/5

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.

Parameters4/5

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.

Purpose4/5

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.

Usage Guidelines3/5

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 ValueA
DestructiveIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoValue type override (auto-resolved if omitted)
valueYesValue to set
addressYesChannel address (e.g. '000A1BE9A71F15:1')
confirmNoSet true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.
valueKeyYesDatapoint name (e.g. 'STATE', 'LEVEL', 'SET_POINT_TEMPERATURE')
interfaceNoInterface name override (auto-resolved if omitted)

TDQS

A4.5/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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/FunctionA
DestructiveIdempotent

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
roomNoRoom name (exact match)
channelYesChannel address (e.g. '000A1BE9A71F15:1')
confirmNoSet true to authorize this write against a protected CCU target (e.g. prod). Unlocks writes to that target for the rest of the session.
functionNoFunction group name (exact match)

TDQS

A4.4/5.0
Behavior4/5

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.

Conciseness5/5

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.

Completeness4/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
profileYesTarget name (see list_ccu_targets)

Output Schema

ParametersJSON Schema
NameRequiredDescription
hostYes
nameYes
portYes
userYes
httpsYes
activeYes
loggedInYes
readonlyYes
protectedYes
writesUnlockedYes

TDQS

A4.9/5.0
Behavior5/5

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.

Conciseness5/5

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.

Completeness5/5

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.

Parameters4/5

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.

Purpose5/5

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.

Usage Guidelines5/5

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.

  1. 4 tool updatesv1.11.0
    • Changedget_system_info13 fields changed
      • removedOutput schema / properties / build / properties / branch / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / build / properties / branch / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / build / properties / builtAt / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / build / properties / builtAt / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / build / properties / commit / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / build / properties / commit / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / build / properties / describe / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / build / properties / describe / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / build / properties / dirty / anyOf
        Removed value: -[
        -  {
        -    "type": "boolean"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / build / properties / dirty / type
        Added value: +[
        +  "boolean",
        +  "null"
        +]
      • removedOutput schema / properties / build / properties / tag / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / build / properties / tag / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • changedOutput schema / properties / role / description
        Previous 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"
    • Changedput_paramset2 fields changed
      • removedInput schema / properties / set / additionalProperties / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  }
        -]
      • addedInput schema / properties / set / additionalProperties / type
        Added value: +[
        +  "string",
        +  "number",
        +  "boolean"
        +]
    • Changedset_system_variable2 fields changed
      • removedInput schema / properties / value / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  }
        -]
      • addedInput schema / properties / value / type
        Added value: +[
        +  "string",
        +  "number",
        +  "boolean"
        +]
    • Changedset_value2 fields changed
      • removedInput schema / properties / value / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "boolean"
        -  }
        -]
      • addedInput schema / properties / value / type
        Added value: +[
        +  "string",
        +  "number",
        +  "boolean"
        +]
  2. 1 tool updatev1.8.0
    • Changedacknowledge_service_messages1 field changed
      • changedInput schema / properties / confirm / description
        Previous 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."
  3. 27 tool updatesv1.7.0
    • Changedacknowledge_service_messages1 field changed
      • addedInput schema / properties / confirm
        Added value: +{
        +  "description": "Set true to authorize this write against a protected CCU target (e.g. prod).",
        +  "type": "boolean"
        +}
    • Changedassign_channel1 field changed
      • addedInput schema / properties / confirm
        Added 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"
        +}
    • Changedcreate_system_variable1 field changed
      • addedInput schema / properties / confirm
        Added 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"
        +}
    • Changeddelete_system_variable1 field changed
      • addedInput schema / properties / confirm
        Added value: +{
        +  "description": "Required true on EVERY call against a protected CCU target (e.g. prod) — deletion never rides on the session unlock.",
        +  "type": "boolean"
        +}
    • Changeddescribe_device_type1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedexecute_program1 field changed
      • addedInput schema / properties / confirm
        Added 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"
        +}
    • Addedget_connection_info
    • Changedget_paramset3 fields changed
      • changedInput schema / properties / paramsetKey / description
        Previous value: -"Paramset to read"New value: +"'VALUES', 'MASTER', or a link partner's channel address (reads that direct link's parameters)"
      • removedInput schema / properties / paramsetKey / enum
        Removed value: -[
        -  "VALUES",
        -  "MASTER",
        -  "LINK"
        -]
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedget_rssi1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedget_service_messages2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedget_system_info11 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / accessNote
        Added value: +{
        +  "description": "Present when ADMIN-only fields are unavailable, explaining why",
        +  "type": "string"
        +}
      • addedOutput schema / properties / address / description
        Added value: +"BidCos address, or \"N/A\" if unavailable (ADMIN-only)"
      • addedOutput schema / properties / build
        Added 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"
        +}
      • addedOutput schema / properties / hmipAddress / description
        Added value: +"HmIP address, or \"N/A\" if unavailable (ADMIN-only)"
      • addedOutput schema / properties / role
        Added 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"
        +}
      • addedOutput schema / properties / serial / description
        Added value: +"Serial number, or \"N/A\" if unavailable (ADMIN-only)"
      • addedOutput schema / properties / target
        Added value: +{
        +  "description": "Active CCU target name",
        +  "type": "string"
        +}
      • addedOutput schema / properties / user
        Added value: +{
        +  "description": "Configured login user for the active target",
        +  "type": "string"
        +}
      • addedOutput schema / properties / version / description
        Added value: +"Firmware version, or \"N/A\" if unavailable (ADMIN-only)"
    • Changedget_value1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedget_values1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Addedlist_ccu_targets
    • Changedlist_devices1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedlist_functions2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedlist_interfaces2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedlist_links1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedlist_programs1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedlist_rooms2 fields changed
      • addedInput schema / $schema
        Added value: +"http://json-schema.org/draft-07/schema#"
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedlist_system_variables1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "CCU target to read from (default: active). See list_ccu_targets.",
        +  "type": "string"
        +}
    • Changedput_paramset1 field changed
      • addedInput schema / properties / confirm
        Added 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"
        +}
    • Changedrun_script1 field changed
      • addedInput schema / properties / confirm
        Added value: +{
        +  "description": "Required true on EVERY call against a protected CCU target (e.g. prod) — scripts never ride on the session unlock.",
        +  "type": "boolean"
        +}
    • Changedset_system_variable1 field changed
      • addedInput schema / properties / confirm
        Added 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"
        +}
    • Changedset_value1 field changed
      • addedInput schema / properties / confirm
        Added 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"
        +}
    • Changedunassign_channel1 field changed
      • addedInput schema / properties / confirm
        Added 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"
        +}
    • Addeduse_ccu
  4. 19 tool updatesv1.3.0
    • Addedacknowledge_service_messages
    • Addedassign_channel
    • Addedcreate_system_variable
    • Addeddelete_system_variable
    • Changeddescribe_device_type1 field changed
      • changedOutput 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"
        +}
    • Changedget_paramset1 field changed
      • changedOutput 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"
        +}
    • Addedget_rssi
    • Changedget_service_messages1 field changed
      • changedOutput 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"
        +}
    • Changedget_system_info1 field changed
      • changedOutput 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"
        +}
    • Changedget_value1 field changed
      • changedOutput 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"
        +}
    • Changedget_values1 field changed
      • changedOutput 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"
        +}
    • Changedlist_devices1 field changed
      • changedOutput 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"
        +}
    • Changedlist_functions1 field changed
      • changedOutput 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"
        +}
    • Changedlist_interfaces1 field changed
      • changedOutput 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"
        +}
    • Addedlist_links
    • Changedlist_programs1 field changed
      • changedOutput 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"
        +}
    • Changedlist_rooms1 field changed
      • changedOutput 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"
        +}
    • Changedlist_system_variables1 field changed
      • changedOutput 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"
        +}
    • Addedunassign_channel
  5. 18 tool updatesv1.1.2
    • First observeddescribe_device_type
    • First observedexecute_program
    • First observedget_paramset
    • First observedget_service_messages
    • First observedget_system_info
    • First observedget_value
    • First observedget_values
    • First observedhelp
    • First observedlist_devices
    • First observedlist_functions
    • First observedlist_interfaces
    • First observedlist_programs
    • First observedlist_rooms
    • First observedlist_system_variables
    • First observedput_paramset
    • First observedrun_script
    • First observedset_system_variable
    • First observedset_value

TDQS

A4/5.0

Scored across 28 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count4/5

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.

Completeness4/5

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

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers