Skip to main content
Glama
uc-remote-mcp

uc-remote-mcp

by b2dmx

An MCP server for the Remote 3 / Remote Two. Works with Claude and any other MCP client.

What it does

  • Layouts: build an activity, device or page.

  • Buttons: ask what a button does, or remap it.

  • Integrations: install, set up and restart them.

  • Backups: snapshot your config, see what changed, restore it.

  • Updates: keep the remote current.

Related MCP server: rc505mk2-mcp

Installation

  1. Install uv. You already have it if you use another Python MCP server.

    powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"   # Windows
    curl -LsSf https://astral.sh/uv/install.sh | sh                                    # macOS / Linux
  2. Add it to your MCP client. For Claude Desktop, edit %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

    {
      "mcpServers": {
        "uc-remote": {
          "command": "uvx",
          "args": ["--from", "git+https://github.com/b2dmx/uc-remote-mcp@v1.0.0", "uc-remote-mcp"]
        }
      }
    }
  3. Restart the client. First launch takes a minute while it builds.

Onboarding

  1. On the remote: Settings → Web Configurator, turn it on and note the PIN.

  2. Tell your AI: "Discover my Unfolded Circle remote and set it up with PIN 1234."

  3. Try: "What does the volume button do in each activity?"

Tips

  • Every change previews first and takes a backup, so it's safe to experiment.

  • Say "Back up my config" before big changes, and "What changed since that backup?" after.

  • Removing an entity also strips the buttons and page items using it.

  • A stopped device? "Restart the Apple TV integration."

  • To update, change the version in your config and restart. Watch → Custom → Releases to hear about new ones.

  • Tested on a Remote 3 (firmware 2.8.x). The Remote Two shares the API but is untested.

More

All the tools → · Field notes →

Tool design informed by ha-mcp. API reference from the Unfolded Circle Core API.

License

The code is MIT. The Unfolded Circle MCP logo and icons (brand-source/, brand/, and the logo images in docs/) are © Goobis, all rights reserved. They are not covered by the MIT license, so please don't reuse them without permission.


Available Tools

41 tools
add_scope_entitiesA

Allow an activity or macro to use more entities. Exposing an entity from an integration is not enough on its own — it must also be added here before a button or page item can use it. Existing entries are preserved.

Inputs: scope_id (required), entity_ids (required), host, scope, +1 more. Returns: object

answer_integration_setupB

Answer the current setup screen and return the next. Send every field the screen asks for; a rejected step ends the flow and it must be restarted.

Inputs: values (required), driver_id (required), host. Returns: object

backup_configA

Dump the entire remote configuration (system, entities, activities, remote-entities, UI pages — full detail) to one JSON file. Defaults to %APPDATA%/uc-remote-mcp/backups/.json, keeping the last 50.

Inputs: host, output_path. Returns: object

bulk_set_button_mappingA

Set the same button binding across many activities at once (e.g. route VOLUME_UP on every activity to the AVR). Filter with activity_ids and/or name_contains; no filter = all activities. Invalid activities are skipped with a reason. One backup before the batch. Defaults to dry_run=True (returns the full per-activity plan); set dry_run=false to apply.

Inputs: button (required), command (required), entity_id (required), host, +5 more. Returns: object

cancel_integration_setupA

Abandon an in-progress setup flow, changing nothing.

Inputs: driver_id (required), host. Returns: object

configure_integration_entitiesA

Expose entities from an integration so activities and pages can use them. Additive; removes nothing. Setup finishing does not do this for you.

Inputs: entity_ids (required), integration_id (required), host, dry_run. Returns: object

confirm_integration_setupA

Answer a confirmation screen ("press the button on the device, then continue") and return the next one. Use answer_integration_setup for screens with fields; this is for the ones without.

Inputs: driver_id (required), host, confirm. Returns: object

create_activityA

Create an activity — a "device" on the remote's home screen.

Pass entity_ids to build from scratch, or clone_from to copy an existing activity/macro/remote-entity; not both. icon takes "uc:name" or "custom:file.png". The empty page the remote creates alongside it is removed, and the result says if it joined the default activity group, which can make its tile power devices on and off.

Inputs: name (required), host, icon, dry_run, +3 more. Returns: object

create_ui_pageA

Add a new page to an activity or remote-entity. scope is "activity" or "remote". grid is {"width": N, "height": M}; items use the same shape as get_ui_page returns. The page is appended last; reorder with set_default_ui_page. Every item command is validated first.

Inputs: grid (required), name (required), scope (required), scope_id (required), +3 more. Returns: object

delete_integrationA

Remove a driver, its instance and all its entities. Also strips every button mapping and page item that used them. Read the preview before applying.

Inputs: driver_id (required), host, dry_run. Returns: object

delete_integration_instanceA

Remove one configured instance and its entities, keeping the driver. The teardown for firmware-shipped drivers. Also strips every button mapping and page item that used those entities — read the preview.

Inputs: integration_id (required), host, dry_run. Returns: object

delete_ui_pageA

Delete a UI page from an 'activity' or 'remote'. IRREVOCABLE on the device — the auto-backup taken before the write is the only way back. Dry-run (default) shows the full page content that would be lost.

Inputs: scope (required), page_id (required), scope_id (required), host, +1 more. Returns: object

diff_configA

Show what changed between the current live config and a backup file (read-only). Reports the operations a restore would perform plus differences that cannot be restored.

Inputs: against_path (required), host. Returns: object

discover_remotesA

Scan the LAN via mDNS for UC remotes. Returns a list of {name, host, port, model, fw, id}.

Inputs: timeout_s. Returns: result

get_activityC

Full activity config: included entities, on/off power sequences, button overrides, and the list of UI pages.

Inputs: activity_id (required), host. Returns: object

get_button_mappingA

Physical-button -> command bindings. scope is 'activity' (needs scope_id=activity_id), 'remote' (needs scope_id=remote entity_id), or 'device' (needs scope_id=target entity_id; returns every binding across all activities and remotes that targets that device).

Inputs: scope (required), host, scope_id. Returns: object

get_deviceB

Full config for one device (entity): features, available commands, current attributes, and options.

Inputs: device_id (required), host. Returns: object

get_integrationB

One integration instance in full, including the entities it has configured.

Inputs: integration_id (required), host. Returns: object

get_integration_setupB

The current screen of a setup flow. 404 means no flow is in progress.

Inputs: driver_id (required), host. Returns: object

get_remote_infoA

Return model, firmware, battery level/status, and currently active activities. Uses the first configured remote if host is not specified.

Inputs: host. Returns: object

get_ui_pageA

Items on one UI page: grid size and each item's position, type, and command. Identify the page by its parent scope ('activity'/'remote'), the scope's entity_id, and the page_id (from list_ui_pages).

Inputs: scope (required), page_id (required), scope_id (required), host. Returns: object

install_integrationA

Install a custom driver from a .tar.gz archive on this machine. There is no in-place update: delete the old driver first. Restart the system afterwards or its setup flow will not start.

Inputs: file_path (required), host, dry_run. Returns: object

list_activitiesC

List all activities with id, name, state, description, and included entities.

Inputs: host. Returns: result

list_device_commandsA

Commands a device exposes, for picking when mapping buttons. Returns {features, simple_commands}.

Inputs: device_id (required), host. Returns: object

list_devicesA

List all configured devices (entities). Each physical device may appear as several entities (e.g. a TV has both a media_player and a remote entity). Optionally filter by entity_type (media_player, remote, light, switch, sensor). Returns {id, name, type, integration, device_class, state} per entity.

Inputs: host, entity_type. Returns: result

list_integration_entitiesB

Entities an integration offers. only_new re-polls the integration and lists what is not exposed yet, which is required after pairing a new device.

Inputs: integration_id (required), host, only_new. Returns: object

list_integrationsA

Installed integration drivers and their configured instances.

device_state is not a health signal: an instance reports CONNECTED while its entities are stale. Check the entities too.

Inputs: host. Returns: object

list_scope_entitiesC

Entities an activity or macro is currently allowed to use. scope is "activity" or "macro" — both keep their own list, and a command naming an entity outside it is rejected.

Inputs: scope_id (required), host, scope. Returns: object

list_ui_pagesA

List UI pages for a scope: 'activity' or 'remote'. scope_id is that entity's id. Returns page ids, names, grids, and item counts.

Inputs: scope (required), scope_id (required), host. Returns: object

remove_scope_entitiesB

Stop an activity or macro using entities. Every button mapping and page item referencing them is removed too, so read the preview before applying.

Inputs: scope_id (required), entity_ids (required), host, scope, +1 more. Returns: object

restart_integrationA

Disable and re-enable an integration. The usual fix when devices stop responding but the integration still claims to be connected.

Inputs: integration_id (required), host, dry_run. Returns: object

restart_remoteA

Restart the remote's "ui", "core", or "system". Sends no device commands and changes no configuration. "ui" is how configuration changes are made to repaint; "system" is required after installing a driver.

Inputs: host, target, dry_run. Returns: object

restore_configA

Restore activities/remotes customization (names, button mappings, UI pages, sequences) from a backup file. First call returns a confirmation_token + full plan without writing; call again with the token and dry_run=false to apply. Auto-backup of the current state is taken before applying.

Inputs: input_path (required), host, dry_run, confirmation_token. Returns: object

send_commandA

Fire a one-off command at a device (entity). Transient (does not change saved config) but affects the device, so defaults to dry_run=True. Set dry_run=false to actually send. Body: PUT /entities/{id}/command {cmd_id, params?}.

Inputs: command (required), device_id (required), host, params, +1 more. Returns: object

set_button_mappingA

Set one physical-button -> command binding on an 'activity' or 'remote'. entity_id is REQUIRED for activities (the command target) and ignored for remotes. Defaults to dry_run=True (shows before/after); auto-backs-up before any real write. Set dry_run=false to apply.

Inputs: scope (required), button (required), command (required), scope_id (required), +5 more. Returns: object

set_default_ui_pageA

Make a page the first/default page of an 'activity' or 'remote' UI (the page shown when it opens). Implemented as a page reorder — the API has no explicit default-page property. Defaults to dry_run=True.

Inputs: scope (required), page_id (required), scope_id (required), host, +1 more. Returns: object

set_integration_enabledC

Enable or disable an integration instance.

Inputs: enabled (required), integration_id (required), host, dry_run. Returns: object

setup_remoteB

First-run setup. Authenticate with admin PIN, create a long-lived API key, and save config. Only needed once per remote.

Inputs: pin (required), host (required), name, port. Returns: object

start_integration_setupA

Begin an integration's setup and return its first screen.

Some drivers require a value up front (usually an API key) and answer "400 Setup data not provided for field: X" without it — pass setup_data={"X": "..."}. A 503 means the driver process is not running yet, which is normal right after installing: restart the system first.

Inputs: driver_id (required), host, setup_data, reconfigure. Returns: object

update_activity_sequenceA

Replace an activity's on and/or off power sequence. Steps are {"type":"command","command":{"entity_id","cmd_id","params"?}} or {"type":"delay","delay":}. Omitted sequence = unchanged; empty list clears it. Command steps are validated against the activity's included entities. Defaults to dry_run=True; auto-backup before any real write.

Inputs: activity_id (required), host, dry_run, on_sequence, +1 more. Returns: object

update_ui_pageA

Update a UI page's name, grid, and/or items on an 'activity' or 'remote'. Omitted fields stay unchanged; an EMPTY items list clears the page. Item commands are validated against the scope before writing. Defaults to dry_run=True; auto-backup before any real write.

Inputs: scope (required), page_id (required), scope_id (required), grid, +4 more. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.2/5.0

    Scored across 41 tools

    Disambiguation4/5

    Most tools target a distinct resource+action, and descriptions explicitly disambiguate close pairs like delete_integration vs delete_integration_instance and answer vs confirm_integration_setup. A few entity-listing tools (list_devices, list_integration_entities, list_scope_entities) require careful reading, but their scope qualifiers make selection possible.

    Naming Consistency5/5

    All tools use snake_case verb_noun names with consistent verbs (list/get/create/update/delete/set/restart). Pluralization is predictable (list_* plural, get_* singular), and modifiers like bulk_ and diff_ are used consistently.

    Tool Count2/5

    At 41 tools, the surface is far beyond the typical 3-15 tool sweet spot and falls in the 'too many' range even for a broad remote-control domain. While most tools are individually justified, the count makes selection harder and suggests consolidation opportunities.

    Completeness3/5

    The surface covers integration lifecycle, setup flows, devices, activities, UI pages, mappings, and backup/restore, which is broad. However, activities have create/get/partial update but no delete/rename, and backup_config has no companion list_backups tool, leaving some dead ends.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers