npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lgtv-control-mcp

v1.1.0

Published

MCP server to control LG webOS TVs from AI clients.

Readme

lgtv-control-mcp

An MCP (Model Context Protocol) server for controlling LG webOS TVs from AI clients like Claude, Codex, GitHub Copilot, and Antigravity. Works with one TV or several: register each TV under a name like "Office" and target it directly, or let commands fall through to a default TV.

Communication uses the webOS SSAP protocol over WebSocket, the same one used by the LG ThinQ app and projects like ColorControl.

Tools

  • add_tv / remove_tv / list_tvs / set_default_tv: manage your TVs by name (see Multiple TVs)
  • set_backlight: backlight 0-100
  • set_peak_brightness: peak brightness off / low / medium / high
  • set_picture_setting / set_picture_mode / get_picture_settings: contrast, brightness, color, and picture mode
  • set_volume / volume_up / volume_down / get_volume / set_mute
  • list_inputs / set_input: switch HDMI and other inputs
  • list_apps / launch_app / close_app / get_foreground_app
  • channel_up / channel_down / set_channel / list_channels / get_current_channel
  • media_play / media_pause / media_stop / media_rewind / media_fast_forward
  • power_off / screen_off / screen_on / get_power_state
  • set_3d_on / set_3d_off
  • show_toast: display a notification on the TV
  • send_button: press a remote button. Compatible names include 0-9, HOME, BACK, ENTER, EXIT, UP, DOWN, LEFT, RIGHT, RED, GREEN, YELLOW, BLUE, POWER, VOLUMEUP, VOLUMEDOWN, MUTE, MENU, CC, DASH, CHANNELUP, CHANNELDOWN, LIST, AD, SAP, PROGRAM, PLAY, PAUSE, STOP, REWIND, FASTFORWARD, GUIDE, AMAZON, NETFLIX, MAGNIFIER_ZOOM, LIVE_ZOOM, 3D_MODE, ASPECT_RATIO, RECENT, RECORD, SCREEN_REMOTE, MYAPPS
  • get_system_info / get_software_info / get_service_list
  • ssap_request: send any raw SSAP command (escape hatch)

Every control tool accepts an optional tv argument with the name of the target TV. Without it, the command goes to the default TV.

Requirements

  • Node.js 18+
  • An LG webOS TV powered on and on the same local network
  • The TV's IP address (Settings > Network)
  • Mobile TV On enabled (Settings > Connection > External Devices > On via Wi-Fi)

Installation

Global install

npm install -g lgtv-control-mcp

This puts the lgtv-control-mcp binary in your PATH. Use command: "lgtv-control-mcp" with no args in your client config.

Via npx (no install)

npx -y lgtv-control-mcp@latest

This does not install the package. The MCP client runs this command each time it starts the server; npm caches the package after the first download.

From source

git clone https://github.com/brunofgmag/lgtv-control-mcp.git
cd lgtv-control-mcp
npm install
npm run build
node dist/index.js

Pairing

The first time you connect, the TV shows a "Connection Request" prompt on screen. Accept it with the remote.

The client key is saved automatically to ~/.lgtv-control-mcp/keys.json and reused on later connections. You don't need to configure it manually. If you want to pin a specific key, copy the value from that file into LGTV_CLIENT_KEY.

Multiple TVs

You can register any number of TVs by name, without touching config files. Just ask your AI:

  • "Add the TV 'Office' with IP 192.168.1.13"
  • "Add the TV 'Living Room' with IP 192.168.1.20"
  • "Which TVs do I have configured?"
  • "Remove the Bedroom TV"

Commands that don't name a TV go to the default TV. The first TV you add becomes the default; to change it, say something like "make the Living Room TV the default". To control a specific TV, name it in the request: "pause the Office TV" or "set the volume to 15 on the Living Room TV".

A few details worth knowing:

  • Adding a TV with a name that already exists updates it, so "change the Office TV's IP to 192.168.1.40" works without removing it first.
  • Names are matched ignoring case; "office" and "Office" are the same TV.
  • Each TV pairs separately. The first command sent to a new TV shows the connection prompt on that screen; accept it with that TV's remote.
  • The list is stored in ~/.lgtv-control-mcp/tvs.json, so it survives restarts and is shared by all your MCP clients.

If you only use one TV, you can skip all of this and set LGTV_HOST instead: when no TVs are registered, commands go to that address.

Client configuration

LGTV_HOST is optional in every example below. It gives you a working single-TV setup right away, but you can leave the env block out entirely and register your TVs by chat afterwards, for example "Add the TV 'Office' with IP 192.168.1.13" (see Multiple TVs). If both exist, registered TVs take precedence over LGTV_HOST.

Claude Desktop

Open Settings → Developer → Edit Config. This opens claude_desktop_config.json directly in your editor. Add the entry and restart the app.

{
  "mcpServers": {
    "lgtv-control": {
      "command": "npx",
      "args": ["-y", "lgtv-control-mcp@latest"],
      "env": { "LGTV_HOST": "192.168.1.50" }
    }
  }
}

If you installed globally, use "command": "lgtv-control-mcp" with "args": [].

Claude Code

The --scope user flag adds the server globally across all your projects:

claude mcp add lgtv-control --scope user --env LGTV_HOST=192.168.1.50 -- npx -y lgtv-control-mcp@latest

If you installed globally, replace npx -y lgtv-control-mcp@latest with just lgtv-control-mcp.

Or add it manually to ~/.claude/settings.json (user-level, global):

{
  "mcpServers": {
    "lgtv-control": {
      "command": "npx",
      "args": ["-y", "lgtv-control-mcp@latest"],
      "env": { "LGTV_HOST": "192.168.1.50" }
    }
  }
}

Codex CLI

Via CLI:

codex mcp add lgtv-control --env LGTV_HOST=192.168.1.50 -- npx -y lgtv-control-mcp@latest

Or in ~/.codex/config.toml:

[mcp_servers."lgtv-control"]
command = "npx"
args = ["-y", "lgtv-control-mcp@latest"]

[mcp_servers."lgtv-control".env]
LGTV_HOST = "192.168.1.50"

GitHub Copilot / VS Code

In .vscode/mcp.json or your user MCP settings:

{
  "servers": {
    "lgtv-control": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "lgtv-control-mcp@latest"],
      "env": { "LGTV_HOST": "192.168.1.50" }
    }
  }
}

For Copilot clients that expect the mcpServers format:

{
  "mcpServers": {
    "lgtv-control": {
      "type": "local",
      "command": "npx",
      "args": ["-y", "lgtv-control-mcp@latest"],
      "env": { "LGTV_HOST": "192.168.1.50" },
      "tools": ["*"]
    }
  }
}

Antigravity

{
  "mcpServers": {
    "lgtv-control": {
      "command": "npx",
      "args": ["-y", "lgtv-control-mcp@latest"],
      "env": { "LGTV_HOST": "192.168.1.50" }
    }
  }
}

Other MCP clients

Most clients that support local MCP via stdio use the same pattern:

{
  "mcpServers": {
    "lgtv-control": {
      "command": "npx",
      "args": ["-y", "lgtv-control-mcp@latest"],
      "env": { "LGTV_HOST": "192.168.1.50" }
    }
  }
}

Environment variables

| Variable | Required | Default | Description | | --- | --- | --- | --- | | LGTV_HOST | no | - | TV IP address; used when no TVs are registered with add_tv | | LGTV_PORT | no | 3001 | 3001 = wss (self-signed TLS); use 3000 for plain ws | | LGTV_CLIENT_KEY | no | - | Pairing key; obtained and saved automatically on first use |

Usage examples

Once configured, try asking your AI:

  • "Set the TV backlight to 30"
  • "Turn up the volume" / "Switch to HDMI 2"
  • "Open Netflix" / "Turn off the TV screen"
  • "Show a 'Dinner's ready' notification on the TV"
  • "Add the TV 'Office' with IP 192.168.1.13"
  • "Open YouTube on the Office TV"
  • "Make the Office TV the default"

Troubleshooting

  • "pairing timed out": accept the connection prompt on the TV screen and try again.
  • "could not connect": check the IP, that the TV is on and on the same network. Try LGTV_PORT=3000.
  • Backlight not changing: some firmware versions require the luna path. The server already tries SSAP first and falls back automatically. Also check that your current picture mode allows manual backlight adjustment.
  • Command reached the wrong TV: ask "which TVs do I have configured?" to see the registered TVs and the current default, then name the TV in the command or change the default.
  • Re-pairing: delete the TV's entry in ~/.lgtv-control-mcp/keys.json to force a new pairing prompt.

How it works

The server opens an SSAP WebSocket with the TV, performs the registration handshake (with pairingType: PROMPT), and sends ssap://... requests. Remote control buttons use a separate pointer socket (getPointerInputSocket). Picture adjustments use setSystemSettings; when the direct SSAP path is rejected by the firmware, the server uses the luna trick (creating and closing an alert whose onclose points to luna://com.webos.settingsservice/setSystemSettings).

License

MIT