MCP server to control an Apple TV (pyatv).
  • Python 97.3%
  • Shell 2.7%
Find a file
2026-06-14 11:24:30 -07:00
.github/workflows Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
src/apple_tv_mcp Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
tests Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
.gitignore Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
.sanity-patterns.json Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
check_pyatv_update.sh Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
LICENSE Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
pair_companion.py Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
pair_interactive.py Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
pyproject.toml Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
qa.py Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
README.md Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00
WHITEPAPER.md Sync to latest sanitized release: license, CI, whitepaper, current code 2026-06-14 11:24:30 -07:00

apple-tv-mcp

Local MCP server that controls your Apple TV 4K over the LAN, using pyatv's Companion protocol with stored pairing credentials, plus YouTube cast control via the YouTube Lounge API.

License: MIT

The problem it solves

Automating the Apple TV normally requires Siri, the physical remote, or Shortcuts. This server exposes the Apple TV as MCP tools so any connected LLM can press buttons, switch apps, type text, and play YouTube videos directly, with no on-screen keyboard navigation and no manual remote needed.

Install

This is a Python MCP server installed in a local venv. Install once, then register it as a stdio transport in your MCP client.

# From the repo root
python -m venv .venv
.venv/bin/pip install -e .

# Run directly
.venv/bin/apple-tv-mcp

For one-shot install via uvx (Python public repo pattern):

uvx --from git+https://github.com/nidamen/apple-tv-mcp apple-tv-mcp

MCP client config

Add the following to your MCP client config (e.g. ~/.claude.json under mcpServers):

{
  "mcpServers": {
    "appletv": {
      "command": "/path/to/apple-tv-mcp/.venv/bin/apple-tv-mcp",
      "args": [],
      "env": {
        "APPLE_TV_HOST": "192.168.1.14",
        "APPLE_TV_CREDS": "~/.config/apple-tv-mcp/companion.creds"
      }
    }
  }
}

Restart Claude Code (or your MCP client) after registering. The tools appear under the prefix appletv_ and youtube_.

Pairing (one-time setup)

Companion (remote control)

# Start pairing -- a PIN appears on the Apple TV screen
APPLE_TV_HOST=192.168.1.14 .venv/bin/python pair_companion.py &

# Write the PIN when it appears on screen
echo 1234 > /tmp/atv_pin

# Copy credentials to the config directory
mkdir -p ~/.config/apple-tv-mcp
cp /tmp/atv_companion_creds.txt ~/.config/apple-tv-mcp/companion.creds

The PIN window is short (about 2 minutes). If it expires, rerun pair_companion.py.

AirPlay (optional, for now-playing metadata)

On tvOS 15+, the now-playing/metadata feed is tunnelled over AirPlay. Without AirPlay credentials appletv_now_playing returns state Idle. Pair AirPlay by setting PAIR_PROTOCOL=airplay and running pair_companion.py again, then save the result to ~/.config/apple-tv-mcp/airplay.creds.

YouTube (cast control)

Open the YouTube app on the Apple TV, go to Settings, select "Link with TV code", and pass the displayed code to youtube_pair. This stores a lounge token at ~/.config/apple-tv-mcp/youtube_lounge.json and enables cast playback.

Complete tool reference

Apple TV control tools

Tool Parameters Purpose
appletv_status none Report paired/reachable/connected status, device model, and tvOS version
appletv_now_playing none Return current title, app, device state, position, and total time
appletv_press key (str, required), repeat (int, 1-50, default 1) Press a remote key N times
appletv_type_text text (str, required) Set the focused on-screen text field to this string in one shot
appletv_clear_text none Clear the focused on-screen text field
appletv_wake none Wake the Apple TV by pressing Home; via HDMI-CEC this also makes the Apple TV the active TV input
appletv_launch_app app (str, required) Launch an app by friendly name or raw tvOS bundle id
appletv_app_list none List installed apps and their bundle ids (may error on tvOS 26)
appletv_keys none Return the accepted key names and known app friendly names

Accepted key names for appletv_press: up, down, left, right, select (aliases: ok, enter), menu / back, home, home_hold, play_pause, play, pause, stop, next, previous / prev, rewind / skip_backward, fast_forward / forward / skip_forward, volume_up, volume_down

Known app names for appletv_launch_app: netflix, youtube, prime / prime video, disney / disney+, hulu, max / hbo max, appletv / apple tv / tv, music, spotify, plex, twitch, paramount / paramount+, peacock, espn, tubi

YouTube tools

Tool Parameters Purpose
youtube_pair code (str, required) One-time pairing with the Apple TV's YouTube app using the "Link with TV code"
youtube_search query (str, required), limit (int, 1-20, default 5) Search YouTube and return video ids, titles, uploaders, and durations
youtube_play query (str, required) Resolve query to top result and cast it to the Apple TV's YouTube app
youtube_enqueue query (str, required) Add the top result to the YouTube up-next queue without interrupting current playback
youtube_play_video_id video_id (str, required) Cast a specific YouTube video id directly
youtube_watch query (str, required) Reliably play a video end-to-end: opens YouTube, casts, and confirms playback position is advancing, automatically clearing the profile picker or any modal
youtube_status none Report whether YouTube is paired and the cast session can reach the app

Environment variables

Variable Default Purpose
APPLE_TV_HOST 192.168.1.14 IP address of the Apple TV
APPLE_TV_CREDS ~/.config/apple-tv-mcp/companion.creds Path to Companion pairing credentials
APPLE_TV_AIRPLAY_CREDS ~/.config/apple-tv-mcp/airplay.creds Path to AirPlay credentials (optional, enables now-playing metadata)
YOUTUBE_LOUNGE_CREDS ~/.config/apple-tv-mcp/youtube_lounge.json Path to YouTube Lounge token (set by youtube_pair)

Transport

stdio, local only. The server runs on the same machine as the MCP client (or on a Raspberry Pi via SSH-stdio). It connects to the Apple TV at APPLE_TV_HOST over the LAN using pyatv's Companion protocol.

Usage examples

"Is the Apple TV on and what is playing?" Call appletv_status to check connectivity, then appletv_now_playing for the current title and app.

"Play 2Pac - Changes on YouTube" Call youtube_watch "2pac changes". It opens YouTube, resolves the query to a video id via yt-dlp, casts it, and confirms playback is advancing before returning.

"Turn the volume down 5 times" Call appletv_press with key="volume_down" and repeat=5.

Limitations

  • Requires the Apple TV to be reachable on the LAN at APPLE_TV_HOST.
  • pyatv Companion pairing must be completed once before any control tool works.
  • appletv_now_playing returns Idle state unless AirPlay credentials are also paired (tvOS 15+ tunnels metadata over AirPlay).
  • appletv_app_list may return an error on tvOS 26 due to Apple API restrictions.
  • YouTube cast (youtube_play, youtube_enqueue, youtube_play_video_id, youtube_watch) requires the YouTube lounge token from youtube_pair and the YouTube app to be open on the Apple TV.
  • tvOS profile picker (the "who's watching" prompt) blocks YouTube casts; youtube_watch auto-clears it by pressing select and retrying, but the other youtube_play* tools do not.
  • AirPlay creds have no standard revoke/refresh UI; if the Apple TV is reset, both Companion and AirPlay credentials must be re-paired.