Skip to main content
Glama
README.md
# webos-tv-mcp

**Let an agent drive your LG TV.**

An MCP server (and a plain CLI) for LG webOS televisions: read what is playing,
list apps, launch them, set the volume, turn the set off.

```
$ webos-tv status
{
  "power": "Active",
  "appId": "youtube.leanback.v4",
  "appTitle": "YouTube AdFree",
  "volume": 18,
  "muted": false,
  "output": "tv_speaker"
}
```

## Why

There are libraries for the webOS socket protocol, but nothing that gives an
agent a small, honest tool surface. This is that: five tools, no magic, and a
README that says exactly what does not work without root.

## Install

```bash
npm i -g @webos-tools/cli      # LG's ares CLI, used for launching apps
npm i -g webos-tv-mcp

webos-tv setup --host 192.168.1.50 --device tv
```

`setup` opens the second-screen socket, the TV shows an **Allow** prompt, and
the client key is saved to `~/.webos-tv/config.json`.

## Use it as an MCP server

```json
{
  "mcpServers": {
    "webos-tv": { "command": "webos-tv", "args": ["mcp"] }
  }
}
```

| Tool | Does |
|---|---|
| `tv_status` | power, foreground app, volume, mute, audio output |
| `tv_apps` | installed apps, optionally filtered |
| `tv_launch` | launch by title (`Netflix`) or id (`netflix`) |
| `tv_volume` | read, set 0-100, mute/unmute |
| `tv_power_off` | standby |

## Or from the terminal

```bash
webos-tv status
webos-tv apps netflix
webos-tv launch "Nature Loop"
webos-tv vol 22
webos-tv vol mute
webos-tv off
```

## How it works

```mermaid
flowchart LR
    A["agent / CLI"] --> B["webos-tv"]
    B -->|"wss :3001<br/>SSAP"| C["TV: second screen"]
    B -->|"ssh :9922<br/>ares-launch"| D["TV: dev mode"]
    C --> E["status, volume, app list"]
    D --> F["launch app"]
```

Two channels, because one is not enough:

- **SSAP** (the second-screen socket on port 3001) answers status, volume and
  the installed-app list.
- **Launch is denied over SSAP** on current firmware — an unsigned client gets
  `401 insufficient permissions` for `system.launcher/launch`. So launching
  shells out to `ares-launch` over SSH, which is what LG's own tooling does.

## Limitations

- **Developer Mode required** for launching (SSH on port 9922).
- **No key input.** Sending remote keys needs a client with
  `CONTROL_INPUT_JOYSTICK`/`CONTROL_MOUSE_AND_KEYBOARD`; this one is paired
  for read + audio, so there is no `tv_key` tool rather than a broken one.
- **No screensaver control.** The system screensaver slot is root-owned.
- **`tv_power_off` is untested on every model.** It uses the documented
  `system/turnOff`; if your set ignores it, wake-on-LAN is not implemented here.

## Security

The client key is a bearer token: anything holding it can read your TV's state
and change its volume. It lives in `~/.webos-tv/config.json` (mode 600
recommended). Revoke it on the TV under Settings → Connection → Device
Connection Settings.

Nothing listens on a port. The MCP server is stdio; the CLI opens a connection,
does one thing and closes it.

## See also

[aerial-tv](https://github.com/taljeri/aerial-tv) - the 4K aerial screensaver
built on the same TV stack.

## Licence

MIT — see [LICENSE](LICENSE).