control_device
Control WeMo smart devices by turning them on, off, toggling, or adjusting brightness levels through the WeMo MCP Server for smart home automation.
Instructions
Control a WeMo device (turn on, off, toggle, or set brightness).
Controls a device by sending turn on, turn off, or toggle commands. For dimmer devices, you can also set the brightness level (1-100). The device must have been discovered via scan_network first.
Args:
device_identifier: Device name (e.g., "Office Light") or IP address (e.g., "192.168.1.100")
action: Action to perform - must be one of: "on", "off", "toggle", "brightness"
brightness: Brightness level (1-100) - only used when action is "brightness" or "on" for dimmer devices
ctx: MCP context injected by FastMCP; used to elicit the correct device when identifier is ambiguousReturns:
Dictionary containing:
- success: Boolean indicating if the action succeeded
- device_name: Name of the device
- action_performed: The action that was executed
- new_state: The state after the action
- brightness: Current brightness level (for dimmers)Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| device_identifier | Yes | ||
| action | Yes | ||
| brightness | No |
Implementation Reference
- src/wemo_mcp_server/server.py:954-1080 (handler)The main implementation of the "control_device" tool.
async def control_device( device_identifier: str, action: str, brightness: int | None = None, ctx: Context | None = None, ) -> dict[str, Any]: """Control a WeMo device (turn on, off, toggle, or set brightness). Controls a device by sending turn on, turn off, or toggle commands. For dimmer devices, you can also set the brightness level (1-100). The device must have been discovered via scan_network first. Args: ---- device_identifier: Device name (e.g., "Office Light") or IP address (e.g., "192.168.1.100") action: Action to perform - must be one of: "on", "off", "toggle", "brightness" brightness: Brightness level (1-100) - only used when action is "brightness" or "on" for dimmer devices ctx: MCP context injected by FastMCP; used to elicit the correct device when identifier is ambiguous Returns: ------- Dictionary containing: - success: Boolean indicating if the action succeeded - device_name: Name of the device - action_performed: The action that was executed - new_state: The state after the action - brightness: Current brightness level (for dimmers) """ # Validate inputs try: params = ControlDeviceParams( device_identifier=device_identifier, action=action, # type: ignore[arg-type] brightness=brightness, ) except ValidationError as e: return { "error": ERR_INVALID_PARAMS, "validation_errors": [ {"field": err["loc"][0], "message": err["msg"], "input": err["input"]} for err in e.errors() ], "success": False, } try: # Find device in memory cache, then reconnect from file cache if needed device = _device_cache.get(params.device_identifier) if not device: device = await _reconnect_device_from_cache(params.device_identifier) if not device: available_names = [ k for k in _device_cache if isinstance(k, str) and not k.replace(".", "").isdigit() ] if ctx is not None and available_names: # Elicit: find closest matches first, fall back to first 5 partial_matches = [ n for n in available_names if params.device_identifier.lower() in n.lower() ] suggestions = partial_matches or available_names[:5] elicit_result = await ctx.elicit( f"Device '{params.device_identifier}' not found. " f"Did you mean one of these: {', '.join(suggestions)}?", schema=_DeviceChoiceSchema, ) if elicit_result.action == "accept" and elicit_result.data: chosen = elicit_result.data.device_name device = _device_cache.get(chosen) if device: params = ControlDeviceParams( device_identifier=chosen, action=params.action, brightness=params.brightness, ) if not device: return { "error": f"Device '{params.device_identifier}' not found in cache", "suggestion": ERR_RUN_SCAN_FIRST, "available_devices": available_names, "success": False, } # Check if device is a dimmer is_dimmer = hasattr(device, "set_brightness") and hasattr(device, "get_brightness") # Validate brightness action for non-dimmers if params.action == "brightness": if not is_dimmer: return { "error": f"Device '{device.name}' is not a dimmer and does not support brightness control", "device_type": type(device).__name__, "success": False, } if params.brightness is None: return { "error": "Brightness value is required when action is 'brightness'", "success": False, } # Perform the action await _perform_device_action(device, params.action, params.brightness, is_dimmer) # Wait for device to respond await asyncio.sleep(0.5) # Build and return result result = await _build_control_result(device, params.action, is_dimmer) logger.info( f"Device '{device.name}' {params.action} successful. New state: {result['new_state']}" + (f" Brightness: {result.get('brightness')}" if is_dimmer else ""), ) return result except Exception as e: logger.error(f"Error controlling device: {e}", exc_info=True) return build_error_response( e, "Control device", context={ "device_identifier": device_identifier, "action": action, }, )