Skip to main content
Glama

show_device_status_ui

Display an interactive status card for WeMo smart devices to view device details and control power states with toggle buttons.

Instructions

Show a device status card with interactive controls.

Returns rich HTML for a single device showing its name, IP, model, and On / Off / Toggle buttons. Supported in Claude Desktop, VS Code, ChatGPT, Goose and any other MCP Apps-compatible host.

Args:

device_identifier: Device name or IP address.

Text-only fallback: use get_device_status + control_device instead.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
device_identifierYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • Implementation of the show_device_status_ui tool, which returns an interactive HTML card for a single WeMo device.
    async def show_device_status_ui(device_identifier: str) -> list[UIResource]:  # type: ignore[return]
        """Show a device status card with interactive controls.
    
        Returns rich HTML for a single device showing its name, IP, model, and
        On / Off / Toggle buttons.  Supported in Claude Desktop, VS Code,
        ChatGPT, Goose and any other MCP Apps-compatible host.
    
        Args:
        ----
            device_identifier: Device name or IP address.
    
        Text-only fallback: use get_device_status + control_device instead.
    
        """
        # Look up device in cache (same lookup order used by other tools)
        device: Any = _device_cache.get(device_identifier)
        if device is None:
            device = await _reconnect_device_from_cache(device_identifier)
    
        if device is not None and hasattr(device, "host"):
            d_name = str(device.name)
            d_host = str(device.host)
            d_model = str(getattr(device, "model_name", type(device).__name__))
        else:
            # Try persistent cache
            try:
                persisted = _cache_manager.load() or {}
                entry = persisted.get(device_identifier, {})
            except Exception:
                entry = {}
            if entry:
                d_name = str(entry.get("name", device_identifier))
                d_host = str(entry.get("host", "?"))
                d_model = str(entry.get("model_name", entry.get("model", "WeMo Device")))
            else:
                d_name = device_identifier
                d_host = "?"
                d_model = "Unknown"
    
        nh = _h(d_name)
        nj = _js(d_name)
    
        status_css = """
    *{box-sizing:border-box;margin:0;padding:0}
    body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
         background:#f1f5f9;color:#1e293b;padding:16px}
    .card{background:#fff;border:1px solid #e2e8f0;border-radius:14px;
          padding:20px;max-width:320px;box-shadow:0 1px 4px rgba(0,0,0,.07)}
    .title{font-size:17px;font-weight:700;margin-bottom:4px}
    .sub{font-size:12px;color:#94a3b8;margin-bottom:18px}
    .row{display:flex;gap:8px}
    button{flex:1;padding:10px;border:none;border-radius:9px;cursor:pointer;
           font-size:14px;font-weight:600;color:#fff;transition:background .15s}
    .btn-on{background:#22c55e}.btn-on:hover{background:#16a34a}
    .btn-off{background:#94a3b8}.btn-off:hover{background:#64748b}
    .btn-toggle{background:#3b82f6}.btn-toggle:hover{background:#2563eb}
    button:disabled{opacity:.55;cursor:not-allowed}
    .footer{margin-top:14px;font-size:11px;color:#cbd5e1;text-align:center}
    """
    
        status_js = """
    function call(action, btn, label) {
      btn.disabled = true; btn.textContent = "\u23f3";
      window.parent.postMessage(
        {type:"tool",payload:{toolName:"control_device",
          params:{device_identifier:NAME,action:action}}},"*");
      setTimeout(function(){ btn.disabled=false; btn.textContent=label; }, 3000);
    }
    """.replace("NAME", f"'{nj}'")
    
        html = (
            '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">'
            f"<style>{status_css}</style></head><body>"
            '<div class="card">'
            f'<div class="title">{nh}</div>'
            f'<div class="sub">{_h(d_host)} · {_h(d_model)}</div>'
            '<div class="row">'
            "<button class=\"btn-on\" onclick=\"call('on',this,'On')\">On</button>"
            "<button class=\"btn-off\" onclick=\"call('off',this,'Off')\">Off</button>"
            "<button class=\"btn-toggle\" onclick=\"call('toggle',this,'Toggle')\">Toggle</button>"
            "</div></div>"
            '<div class="footer">wemo-mcp-server · MCP Apps</div>'
            f"<script>{status_js}</script></body></html>"
        )
        resource = create_ui_resource(
            {
                "uri": "ui://wemo/device-status",
                "content": {"type": "rawHtml", "htmlString": html},
                "encoding": "text",
            }
        )
        return [resource]  # type: ignore[return-value]
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: it returns rich HTML with interactive controls (buttons), specifies the supported hosts, and mentions a text-only fallback. However, it doesn't address potential behavioral aspects like error handling, performance characteristics, or authentication requirements, leaving some gaps for a tool with interactive elements.

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 well-structured and front-loaded: the first sentence states the core purpose, followed by details on output format, supported hosts, parameter explanation, and fallback guidance. Every sentence adds value without redundancy, and the use of sections (e.g., 'Args:') improves readability while maintaining brevity.

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 (interactive UI output), no annotations, and the presence of an output schema (which handles return values), the description is complete enough. It covers purpose, usage context, parameter meaning, and alternatives, addressing key aspects an agent needs to select and invoke the tool correctly in the absence of structured behavioral annotations.

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 schema description coverage is 0%, so the description must compensate. It provides a clear parameter section explaining 'device_identifier: Device name or IP address,' which adds essential semantic meaning beyond the schema's generic 'string' type. However, it doesn't elaborate on format constraints (e.g., IP address validation) or provide examples, which could further enhance understanding.

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: 'Show a device status card with interactive controls' and specifies it returns 'rich HTML for a single device showing its name, IP, model, and On / Off / Toggle buttons.' This is specific (verb+resource+output format) and distinguishes it from sibling tools like get_device_status (which presumably returns data without UI) and control_device (which performs actions without displaying status).

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 provides explicit guidance on when to use this tool versus alternatives: 'Supported in Claude Desktop, VS Code, ChatGPT, Goose and any other MCP Apps-compatible host' indicates the required context, and 'Text-only fallback: use get_device_status + control_device instead' explicitly names alternative tools for different scenarios. This covers both when-to-use (interactive hosts) and when-not-to-use (text-only contexts).

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/apiarya/wemo-mcp-server'

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