coolercontrol-mcp
# coolercontrol-mcp
An [MCP](https://modelcontextprotocol.io) server for [CoolerControl](https://gitlab.com/coolercontrol/coolercontrol). It lets Claude and other MCP clients read your temperatures and fan speeds, and change fan profiles, fixed speeds and modes, through the CoolerControl daemon's REST API.
Tested against CoolerControl 5.1.1.
## Tools
All 32 tools. ✏️ marks tools that change something; they need a token with **Write Access**.
| Area | Tool | What it does |
|---|---|---|
| Monitoring | `get_status` | Latest temperatures (°C), fan rpm and duty, power and clocks; optionally one device or channel |
| | `list_devices` | Devices, their fan channels and their temperature sensors |
| | `get_channel_settings` | What each fan channel is set to: a profile, a fixed duty, or the default |
| | `get_health` | Daemon version, uptime and warning count |
| Fan channels | `set_fixed_speed` ✏️ | Set a channel to a fixed duty % (refuses values below `COOLERCONTROL_MIN_DUTY`) |
| | `apply_profile` ✏️ | Assign a profile to a channel |
| | `reset_channel` ✏️ | Return a channel to its hardware default |
| Profiles | `list_profiles` | Profiles with their curves and temperature sources |
| | `create_profile` ✏️ | Create a Fixed, Graph, Mix or Overlay profile |
| | `update_profile` ✏️ | Change some fields of a profile; the rest stay as they are |
| | `delete_profile` ✏️ | Delete a profile; refuses while anything uses it unless `force` is set |
| Modes | `list_modes` | Saved modes and which one is active |
| | `get_mode` | The channel settings saved in a mode |
| | `create_mode` ✏️ | Save the current settings of every channel as a new mode |
| | `update_mode` ✏️ | Rename a mode and/or re-save it from the current settings |
| | `duplicate_mode` ✏️ | Copy a mode |
| | `delete_mode` ✏️ | Delete a mode |
| | `activate_mode` ✏️ | Apply a mode's saved settings |
| Functions | `list_functions` | Functions that control how quickly profiles change duty |
| | `create_function` ✏️ | Create a function; unset fields copy the Default Function |
| | `update_function` ✏️ | Change some fields of a function |
| | `delete_function` ✏️ | Delete a function; refuses while a profile uses it unless `force` is set |
| Alerts | `list_alerts` | Alerts and the recent alert log |
| | `create_alert` ✏️ | Create an alert on a temperature, duty, load, rpm or frequency |
| | `update_alert` ✏️ | Change some fields of an alert |
| | `delete_alert` ✏️ | Delete an alert |
| Custom sensors | `list_custom_sensors` | Custom sensors |
| | `create_custom_sensor` ✏️ | Create a sensor that mixes, offsets or averages other sensors, or reads a file |
| | `update_custom_sensor` ✏️ | Change some fields of a custom sensor |
| | `delete_custom_sensor` ✏️ | Delete a custom sensor; refuses while a profile uses it unless `force` is set |
| Any other endpoint | `list_api_endpoints` | List the 83 REST endpoints a token can call |
| | `call_api` ✏️ | Call any of them: lighting, LCD images, calibration, name overrides, daemon settings, stats, detection, power profiles, logs, metrics |
Devices can be given by uid, uid prefix (8+ characters) or exact name. Channels can be given by name (`fan1`) or label (`Intake`). Profiles, modes, functions and alerts can be given by uid or name.
**Not supported:** login and passwords, access-token management, daemon shutdown, plugins, stress tests, saving UI settings and the live event streams. CoolerControl accepts only a browser session for these, not a token.
## Setup
1. **Create a token.** In the CoolerControl UI, open **Access Protection → Create Token**. Leave **Write Access** off for a monitoring-only token; the daemon then rejects the write tools with a clear error. Turn it on to let the client change fan settings.
2. **Build:**
```sh
git clone https://github.com/ryanpag3/coolercontrol-mcp.git
cd coolercontrol-mcp
npm install # also builds dist/
```
3. **Register it with your MCP client.**
Claude Code:
```sh
claude mcp add coolercontrol -s user \
-e COOLERCONTROL_TOKEN=cc_... \
-- node /path/to/coolercontrol-mcp/dist/index.js
```
Claude Desktop (or any client that uses a JSON config):
```json
{
"mcpServers": {
"coolercontrol": {
"command": "node",
"args": ["/path/to/coolercontrol-mcp/dist/index.js"],
"env": { "COOLERCONTROL_TOKEN": "cc_..." }
}
}
}
```
### Docker
A multi-arch image (amd64, arm64) is published to GHCR. The daemon listens on `127.0.0.1` by default, so the container needs `--network host` to reach it:
```sh
claude mcp add coolercontrol -s user -e COOLERCONTROL_TOKEN=cc_... -- \
docker run -i --rm --network host -e COOLERCONTROL_TOKEN ghcr.io/ryanpag3/coolercontrol-mcp:latest
```
```json
{
"mcpServers": {
"coolercontrol": {
"command": "docker",
"args": ["run", "-i", "--rm", "--network", "host", "-e", "COOLERCONTROL_TOKEN",
"ghcr.io/ryanpag3/coolercontrol-mcp:latest"],
"env": { "COOLERCONTROL_TOKEN": "cc_..." }
}
}
}
```
Tags: `latest` (master), `sha-<commit>`, and `X.Y.Z` / `X.Y` for `vX.Y.Z` git tags.
## Configuration
| Variable | Default | |
|---|---|---|
| `COOLERCONTROL_TOKEN` | *(required)* | `cc_...` access token |
| `COOLERCONTROL_URL` | `http://localhost:11987` | Daemon URL. Use `https://` for a remote daemon with TLS enabled |
| `COOLERCONTROL_MIN_DUTY` | `20` | Lowest duty % that `set_fixed_speed` will apply. A guard against stopping a pump or fan by accident; set it to `0` to allow anything the hardware accepts |
| `COOLERCONTROL_INSECURE_TLS` | `false` | Accept self-signed certificates |
The minimum-duty floor applies only to `set_fixed_speed`. Profiles keep whatever curve you gave them in CoolerControl.
## Development
```sh
npm run build # tsc → dist/
npm test # vitest
npx @modelcontextprotocol/inspector -e COOLERCONTROL_TOKEN=cc_... node dist/index.js
```
## License
MIT
TDQS
Scored across 32 tools
Tools are grouped by distinct resources and actions (profiles, modes, functions, alerts, custom sensors, channel operations), and most boundaries are clear. The main ambiguity is the generic call_api/list_api_endpoints pair, which overlaps every dedicated tool, but the description explicitly steers agents toward dedicated tools when available.
All tool names use consistent snake_case with predictable verb_noun or action_resource structure. Variations like activate_mode, apply_profile, reset_channel, and set_fixed_speed are specific but still follow the same convention.
32 tools is heavy for a fan-control server, even though the domain has many subresources with full CRUD families. Several conveniences (duplicate_mode) and meta-REST tools push the set beyond a tightly scoped surface, making it borderline over-scoped.
The set covers CRUD for modes, profiles, functions, alerts, and custom sensors, plus device/status reads and channel assignment/reset operations. The list_api_endpoints/call_api escape hatch also fills gaps for lighting, LCD, calibration, and other daemon endpoints.