Skip to main content
Glama
adrighem

Domoticz MCP Server

by adrighem

control_blinds

Manage blinds and covers in Domoticz with commands Open, Close, or Stop. Identify the device by its index or name.

Instructions

Control blinds or covers.

Args: command: Must be 'Open', 'Close', or 'Stop'. idx: Device index. name: Device name.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
commandYes
idxNo
nameNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function for the 'control_blinds' tool. It accepts a 'command' (Open, Close, or Stop), resolves the device idx by idx or name, and calls the Domoticz switchlight API with the capitalized command.
    @mcp.tool()
    async def control_blinds(command: str, idx: int | None = None, name: str | None = None) -> str:
        """Control blinds or covers.
        
        Args:
            command: Must be 'Open', 'Close', or 'Stop'.
            idx: Device index.
            name: Device name.
        """
        if idx is None and name is None:
            return '{"status": "error", "message": "Must provide either idx or name"}'
        if command.capitalize() not in ['Open', 'Close', 'Stop']:
            return '{"status": "error", "message": "command must be \'Open\', \'Close\', or \'Stop\'"}'
        async with create_client() as client:
            resolved_idx = await _resolve_device_idx(client, idx, name)
            if resolved_idx is None:
                return '{"status": "error", "message": "Device not found"}'
            response = await _do_request(client, "GET", f"{DOMOTICZ_API_URL}?type=command¶m=switchlight&idx={resolved_idx}&switchcmd={command.capitalize()}")
            return response.text
  • The @mcp.tool() decorator registers 'control_blinds' as an MCP tool. The function signature and docstring define the input schema: 'command' (str, required), 'idx' (int, optional), 'name' (str, optional).
    @mcp.tool()
    async def control_blinds(command: str, idx: int | None = None, name: str | None = None) -> str:
        """Control blinds or covers.
  • The @mcp.tool() decorator on line 644 registers this function as an MCP tool named 'control_blinds' with the FastMCP server instance.
    @mcp.tool()
    async def control_blinds(command: str, idx: int | None = None, name: str | None = None) -> str:
        """Control blinds or covers.
        
        Args:
            command: Must be 'Open', 'Close', or 'Stop'.
            idx: Device index.
            name: Device name.
        """
        if idx is None and name is None:
            return '{"status": "error", "message": "Must provide either idx or name"}'
        if command.capitalize() not in ['Open', 'Close', 'Stop']:
            return '{"status": "error", "message": "command must be \'Open\', \'Close\', or \'Stop\'"}'
        async with create_client() as client:
            resolved_idx = await _resolve_device_idx(client, idx, name)
            if resolved_idx is None:
                return '{"status": "error", "message": "Device not found"}'
            response = await _do_request(client, "GET", f"{DOMOTICZ_API_URL}?type=command¶m=switchlight&idx={resolved_idx}&switchcmd={command.capitalize()}")
            return response.text
  • Test for the control_blinds tool. Imports control_blinds, mocks the device resolution and API call, then invokes await control_blinds('Open', name='Kitchen Light').
    @pytest.mark.asyncio
    @respx.mock
    async def test_device_control_tools():
        from domoticz_mcp.server import (
            set_switch_state, set_dimmer_level, set_temperature_setpoint, control_blinds
        )
        
        # Mock resolution for Kitchen Light (idx 2)
        respx.get(f"{DOMOTICZ_API_URL}?type=command¶m=getdevices&filter=all&used=true").mock(
            return_value=Response(200, json=DEVICES_MOCK_RESPONSE)
        )
        
        # set_switch_state
        respx.get(f"{DOMOTICZ_API_URL}?type=command¶m=switchlight&idx=2&switchcmd=On").mock(
            return_value=Response(200, json={"status": "OK"})
        )
        await set_switch_state("On", name="Kitchen Light")
        
        # set_dimmer_level
        respx.get(f"{DOMOTICZ_API_URL}?type=command¶m=switchlight&idx=2&switchcmd=Set%20Level&level=50").mock(
            return_value=Response(200, json={"status": "OK"})
        )
        await set_dimmer_level(50, name="Kitchen Light")
        
        # set_temperature_setpoint
        # Thermostat is idx 45 in DEVICES_MOCK_RESPONSE
        respx.get(f"{DOMOTICZ_API_URL}?type=command¶m=setsetpoint&idx=45&setpoint=21.5").mock(
            return_value=Response(200, json={"status": "OK"})
        )
        await set_temperature_setpoint(21.5, name="Thermostat")
        
        # control_blinds
        # Let's say Kitchen Light is actually a blind for this test
        respx.get(f"{DOMOTICZ_API_URL}?type=command¶m=switchlight&idx=2&switchcmd=Open").mock(
            return_value=Response(200, json={"status": "OK"})
        )
        await control_blinds("Open", name="Kitchen Light")
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are present, so the description must disclose behavioral traits. It does not mention that the tool modifies device state, whether it is destructive, or any required authorizations. The valid commands (Open, Close, Stop) imply mutability, but no further context is given.

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 extremely concise, using only four lines to convey the purpose and arguments. It is front-loaded with the main action ('Control blinds or covers'), and every sentence serves a clear function.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although an output schema exists (reducing need to describe returns), the description omits important context such as how to uniquely identify a device, what happens when both idx and name are provided, and any constraints or side effects. This is insufficient for a tool with three parameters and no schema descriptions.

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 description adds meaning beyond the schema by specifying valid command values ('Must be Open, Close, or Stop') and briefly explaining idx and name. However, it does not clarify how to use idx vs. name, nor does it describe error handling or precedence. With 0% schema description coverage, the description partially compensates but lacks depth.

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 it controls blinds or covers, and the command parameter specifies allowed actions (Open, Close, Stop). The tool name and description align well, and no sibling tool directly corresponds to blind control, so differentiation is implicit.

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?

No guidance is provided on when to use this tool versus alternatives like set_switch_state or toggle_switch. The description simply states 'Control blinds or covers' without any context on prerequisites, device selection, or conflict resolution with sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adrighem/domoticz-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server