{
  "markdown": "<!-- mcp-name: io.github.trevor-nichols/appletv-mcp -->\n\n# Apple TV MCP: A local MCP server that lets AI agents control — and see — your Apple TV\n\n<p align=\"center\">\n  <img\n    src=\"docs/assets/apple-tv-mcp-hero.png\"\n    alt=\"Apple TV MCP — AI control and visual navigation for Apple TV\"\n    width=\"100%\"\n  />\n</p>\n\nOpen apps, navigate tvOS, control playback, type searches, adjust volume, manage power, and take screenshots so a multimodal agent can actually inspect what happened.\n\n```text\nYou:\nOpen YouTube and search for OpenAI.\n\nAgent:\n→ opens YouTube\n→ takes a screenshot\n→ sees the current interface\n→ navigates to Search\n→ types \"OpenAI\"\n→ takes another screenshot\n→ verifies the results\n```\n\nApple TV MCP turns your Apple TV into a locally controlled, visually observable device for MCP-capable AI agents.\n\nNo hosted backend. No custom Apple TV app. No cloud account.\n\n---\n\n## Why Apple TV MCP?\n\nMost Apple TV automation is blind.\n\nA script can press Right or Select, but it usually has no idea what appeared on the screen afterward.\n\nApple TV MCP combines **semantic control** with **point-in-time visual observation**.\n\n| Traditional Apple TV automation  | Apple TV MCP                                                |\n| -------------------------------- | ----------------------------------------------------------- |\n| Send blind remote commands       | Take screenshots between actions                            |\n| Build app-specific scripts       | Navigate arbitrary tvOS interfaces                          |\n| Guess whether an action worked   | Inspect the screen and verify                               |\n| Custom integration per AI system | Standard MCP tool interface                                 |\n| Remote commands only             | Apps, playback, text, power, volume, navigation, and vision |\n\nThe result is a feedback loop an AI agent can actually use:\n\n```text\nscreenshot\n    ↓\nmodel sees tvOS\n    ↓\nchooses an action\n    ↓\npress / type / open\n    ↓\nscreenshot again\n    ↓\nverify\n```\n\nSemantic tools are still preferred whenever possible. Screenshots make the difference when the task requires navigating an interface that does not expose a direct API.\n\n---\n\n## Install in seconds\n\nApple TV MCP requires Python 3.14.\n\n### Recommended\n\n```bash\nuv tool install appletv-mcp\n```\n\nOr:\n\n```bash\npipx install appletv-mcp\n```\n\nThen pair your Apple TV:\n\n```bash\natvremote wizard\n```\n\nConfigure Apple TV MCP:\n\n```bash\nappletv-mcp configure\n```\n\nCheck the setup:\n\n```bash\nappletv-mcp doctor\n```\n\nAnd start the MCP server:\n\n```bash\nappletv-mcp serve\n```\n\n### From source\n\n```bash\ngit clone https://github.com/trevor-nichols/appletv-mcp.git\ncd appletv-mcp\nuv sync --locked\nuv run appletv-mcp configure\nuv run appletv-mcp doctor\nuv run appletv-mcp serve\n```\n\n---\n\n## What can it do?\n\nApple TV MCP exposes fourteen tools grouped around what an agent actually wants to accomplish.\n\n### See\n\n* Take a screenshot of the current Apple TV screen\n* Read device, connection, playback, and media state\n* Inspect available Apple TV capabilities\n\n### Apps\n\n* List installed applications\n* Open an application by name\n* Open an application by bundle identifier\n* Open deep links and custom application URLs\n\n### Navigate\n\n* Up\n* Down\n* Left\n* Right\n* Select\n* Back\n* Home\n* Menu\n* Other supported remote actions\n\nRemote navigation is intentionally treated as non-idempotent. Apple TV MCP does not blindly replay navigation commands after an uncertain connection failure.\n\n### Playback\n\n* Play\n* Pause\n* Toggle play/pause\n* Stop\n* Next\n* Previous\n* Seek to an absolute position\n* Skip forward or backward\n\n### Text\n\nType directly into a focused tvOS text field.\n\nThis is useful for:\n\n* Search\n* Usernames\n* App navigation\n* Query entry\n\n### Volume\n\n* Read volume when available\n* Set an absolute volume level\n* Adjust volume relatively\n\n### Power\n\n* Turn the Apple TV on\n* Turn the Apple TV off\n\nPower operations use different retry semantics so a reconnect attempt cannot accidentally wake a device immediately after a successful power-off command.\n\n---\n\n## Give your agent eyes\n\nThe optional screenshot backend is what makes Apple TV MCP more than a remote control.\n\nThe MCP tool:\n\n```text\napple_tv_screenshot\n```\n\nreturns the current Apple TV screen as native MCP image content.\n\nThat means a multimodal MCP client can call the tool and inspect the returned image directly.\n\nFor example:\n\n```text\nAgent:\napple_tv_screenshot()\n\n→ sees the Apple TV Home Screen\n→ sees YouTube highlighted\n\napple_tv_press(button=\"select\")\n\napple_tv_screenshot()\n\n→ sees the YouTube interface\n```\n\nThe model does not need access to a local `screen.png` path and does not receive base64 inside a text response.\n\nThe PNG itself is returned through MCP.\n\n### Screenshots are point-in-time\n\nApple TV MCP does **not** continuously watch the screen.\n\nA screenshot describes what was rendered at the moment it was captured.\n\nIf the agent performs another action afterward, the previous screenshot may already be stale.\n\nThe intended pattern is:\n\n```text\nobserve\n→ act\n→ observe\n→ verify\n```\n\n---\n\n## Enable screenshots\n\nScreenshot support is optional.\n\nApple TV control continues to work normally without it.\n\nInstall the separate helper:\n\n```bash\nuv tool install appletv-screenshot\n```\n\nThe screenshot system uses a separate Apple developer / RemoteXPC pairing from the pairing used by `pyatv`.\n\nPair for developer access:\n\n```bash\npymobiledevice3 remote pair\n```\n\nThen configure the screenshot helper for one Apple TV:\n\n```bash\nappletv-screenshot configure --udid <UDID>\n```\n\nVerify everything together:\n\n```bash\nappletv-mcp doctor\n```\n\nA healthy installation will report both Apple TV control and screen capture.\n\nThe screenshot helper has its own configuration, dependencies, and lifecycle. `pymobiledevice3` is not imported by the main `appletv-mcp` package.\n\nFor deeper screenshot setup and transport troubleshooting, see:\n\n```text\nsidecars/appletv-screenshot/README.md\n```\n\n---\n\n## Quick start\n\nThe complete happy path is:\n\n```bash\n# Install\nuv tool install appletv-mcp\n\n# Pair for Apple TV control\natvremote wizard\n\n# Choose the Apple TV\nappletv-mcp configure\n\n# Optional: install visual observation\nuv tool install appletv-screenshot\n\n# Optional: developer pairing for screenshots\npymobiledevice3 remote pair\nappletv-screenshot configure --udid <UDID>\n\n# Verify\nappletv-mcp doctor\n\n# Run the MCP server\nappletv-mcp serve\n```\n\n---\n\n## Connect your MCP client\n\nApple TV MCP uses local **stdio MCP transport**.\n\nAny MCP client capable of launching a local stdio server can use it.\n\nA typical configuration looks like:\n\n```json\n{\n  \"mcpServers\": {\n    \"appletv-mcp\": {\n      \"command\": \"appletv-mcp\",\n      \"args\": [\"serve\"]\n    }\n  }\n}\n```\n\nIf Apple TV MCP is running from a cloned repository instead:\n\n```json\n{\n  \"mcpServers\": {\n    \"appletv-mcp\": {\n      \"command\": \"uv\",\n      \"args\": [\n        \"--directory\",\n        \"/absolute/path/to/appletv-mcp\",\n        \"run\",\n        \"appletv-mcp\",\n        \"serve\"\n      ]\n    }\n  }\n}\n```\n\nThe server does not expose an HTTP endpoint and does not require OAuth.\n\n---\n\n## Tools\n\n| Tool                     | Purpose                                    |\n| ------------------------ | ------------------------------------------ |\n| `apple_tv_status`        | Read structured device and playback state  |\n| `apple_tv_capabilities`  | Inspect normalized feature availability    |\n| `apple_tv_list_apps`     | List launchable applications               |\n| `apple_tv_power`         | Turn the Apple TV on or off                |\n| `apple_tv_open_app`      | Open an application                        |\n| `apple_tv_open_url`      | Open a URL or deep link                    |\n| `apple_tv_press`         | Press Apple TV remote buttons              |\n| `apple_tv_playback`      | Control playback                           |\n| `apple_tv_seek`          | Seek to an absolute playback position      |\n| `apple_tv_skip`          | Skip forward or backward                   |\n| `apple_tv_set_text`      | Replace focused keyboard text              |\n| `apple_tv_set_volume`    | Set an absolute volume                     |\n| `apple_tv_adjust_volume` | Adjust volume relatively                   |\n| `apple_tv_screenshot`    | Return one screenshot as MCP image content |\n\nThe screenshot tool is the only tool that returns image content rather than a structured result.\n\n---\n\n## How it works\n\nApple TV MCP keeps control and visual observation intentionally separate.\n\n```text\n                         AI Agent\n                            │\n                            ▼\n                      Apple TV MCP\n                      /           \\\n                     /             \\\n                    ▼               ▼\n              semantic control   screen capture\n                    │               │\n                  pyatv      appletv-screenshot\n                    │               │\n                    │         pymobiledevice3\n                    │               │\n                    │          RemoteXPC / DVT\n                    │               │\n                    └──── Apple TV ─┘\n```\n\n### Control\n\nApple TV control is provided through `pyatv`.\n\nApple TV MCP adds a semantic application layer on top for:\n\n* deterministic app resolution\n* capability checking\n* connection lifecycle\n* safe retry behavior\n* non-idempotent command protection\n* normalized MCP results\n\nThe stable Apple TV identifier is authoritative.\n\nThe last known IP address is only an optimization. If the Apple TV changes addresses, Apple TV MCP can rediscover it by identifier and update the preferred host.\n\n### Vision\n\nScreenshots use the separate `appletv-screenshot` helper.\n\nThe helper uses `pymobiledevice3` to reach Apple's developer services over RemoteXPC and request a screenshot through DVT.\n\nIts default transport strategy is:\n\n```text\nmacOS:\nnative → userspace → tunneld\n\nLinux / Windows:\nuserspace → tunneld\n```\n\nThe normal Wi-Fi userspace path does not require root or a permanently running tunnel daemon.\n\nThe helper exists as a separate process so its protocol stack, dependencies, pairing records, and failure modes remain isolated from Apple TV control.\n\n`pymobiledevice3` is confined to the separately distributed `appletv-screenshot` helper. The main `appletv-mcp` package does not import or bundle it; the two processes communicate through a narrow command-line/file contract.\n\n---\n\n## Designed for agents\n\nThe MCP interface intentionally exposes semantic operations rather than raw Apple protocols.\n\nAn agent should think:\n\n```text\nopen YouTube\npause playback\nseek to 2:00\ntype \"Severance\"\nset volume to 35%\ntake a screenshot\n```\n\nnot:\n\n```text\nsend Companion command\ncall MRP endpoint\nconstruct RemoteXPC request\n```\n\nWhen a semantic operation exists, use it.\n\nVisual navigation is the fallback for interfaces that require it.\n\n---\n\n## Privacy and security\n\nApple TV MCP is designed to remain local.\n\n* No hosted Apple TV MCP backend\n* No cloud account\n* MCP uses local stdio transport\n* Apple TV pairing credentials stay on the user's machine\n* RemoteXPC pairing records stay with the screenshot helper\n* Credentials are never MCP parameters\n* Credentials are never returned to the model\n* Keyboard text is not emitted into normal logs\n* Screenshots are captured only when explicitly requested\n* Screenshot bytes are not logged\n* Screenshots are stored only in a private temporary directory during capture\n* Temporary screenshot files are deleted after the MCP result is created\n* Screenshot capture does not run automatically after commands\n* The helper is launched without a shell\n* No DRM circumvention is attempted\n\nDebug mode also keeps raw `pyatv` protocol logging disabled because low-level Companion traffic can contain sensitive keyboard and pairing payloads.\n\n---\n\n## Protected video\n\nStreaming applications may protect video using DRM.\n\nIn that case, screenshots can contain:\n\n```text\nblack video\nblank video\nredacted video\n```\n\nwhile menus or playback controls remain visible.\n\nThat is expected.\n\nApple TV MCP does not interpret a black protected video region as proof that:\n\n* playback failed\n* the Apple TV turned off\n* screenshot capture failed\n\nand it does not attempt to bypass DRM.\n\n---\n\n## Limitations\n\nApple TV MCP intentionally has a narrow initial scope.\n\n### One Apple TV\n\nEach server configuration controls one Apple TV.\n\nMulti-device routing is not currently part of the public MCP interface.\n\n### Screenshots are not video\n\n`apple_tv_screenshot` captures one frame at a time.\n\nThere is no:\n\n* continuous stream\n* background screen monitoring\n* screen recording\n* automatic screenshot loop\n\n### Focus is visual, not semantic\n\n`pyatv` does not provide a universal signal for the currently highlighted tvOS element.\n\nAn agent can use screenshots to infer focus where appropriate.\n\n### `media_app` is not `foreground_app`\n\nApple TV status may identify the application associated with current media metadata.\n\nThat does not independently guarantee which application is visually in the foreground.\n\n### Apple developer services can change\n\nScreenshot support relies on Apple developer protocols exposed through `pymobiledevice3`.\n\ntvOS changes may require future compatibility updates.\n\n### Screenshot support is optional\n\nEvery non-screenshot Apple TV MCP tool works without the screenshot helper installed.\n\n---\n\n## Configuration\n\nApple TV MCP stores application configuration in the platform-standard config directory.\n\nTypical settings include:\n\n```json\n{\n  \"device_identifier\": \"...\",\n  \"device_name\": \"Living Room\",\n  \"preferred_host\": \"192.168.1.10\",\n  \"scan_timeout_seconds\": 5.0,\n  \"command_timeout_seconds\": 15.0,\n  \"screen_capture\": {\n    \"command\": \"appletv-screenshot\",\n    \"timeout_seconds\": 20.0,\n    \"max_image_bytes\": 33554432\n  }\n}\n```\n\nPairing credentials are not stored in this file.\n\nIf an MCP host launches processes with a minimal `PATH`, set `screen_capture.command` to the absolute path of the screenshot helper.\n\nExisting configuration files from Apple TV MCP v0.1 remain compatible.\n\n---\n\n## Doctor\n\nRun:\n\n```bash\nappletv-mcp doctor\n```\n\nto diagnose the complete installation.\n\nIt checks areas such as:\n\n```text\nconfiguration\npyatv storage\nApple TV discovery\nstable device identity\nconnection\ncapabilities\nscreenshot helper\nscreenshot helper contract\nscreen-capture target\nreal screenshot capture\n```\n\nScreenshot support is optional.\n\nIf the helper is not installed, Doctor reports it as skipped rather than treating Apple TV control as broken.\n\n---\n\n## Troubleshooting\n\n### Apple TV not found\n\nConfirm:\n\n* the Apple TV is powered on\n* the computer and Apple TV are on the same local network\n* `atvremote wizard` completed successfully\n\nThen rerun:\n\n```bash\nappletv-mcp configure\nappletv-mcp doctor\n```\n\n### Apple TV IP changed\n\nThat is expected.\n\nApple TV MCP identifies the configured device by its stable identifier rather than trusting an old IP address.\n\n### App will not open\n\nUse:\n\n```text\napple_tv_list_apps\n```\n\nto see the applications currently exposed by the device.\n\nApplication-name matching is deterministic rather than fuzzy.\n\n### Text entry fails\n\nA text field must already be focused on the Apple TV.\n\n### Screenshot helper not found\n\nInstall it:\n\n```bash\nuv tool install appletv-screenshot\n```\n\nor configure Apple TV MCP with its absolute path.\n\n### Screenshot target is not configured\n\nRun:\n\n```bash\nappletv-screenshot configure --udid <UDID>\n```\n\n### Screenshot pairing fails\n\nDeveloper screenshot pairing is separate from `atvremote`.\n\nRun:\n\n```bash\npymobiledevice3 remote pair\n```\n\n### Screenshot is black\n\nProtected content may intentionally hide its video frame.\n\nTry opening a tvOS menu or application interface and capture again.\n\n---\n\n## Development\n\nClone the repository:\n\n```bash\ngit clone https://github.com/trevor-nichols/appletv-mcp.git\ncd appletv-mcp\n```\n\nInstall:\n\n```bash\nuv sync --locked\n```\n\nRun the complete root quality gate:\n\n```bash\nuv run ruff check .\nuv run ruff format --check .\nuv run pyright\nuv run pytest\nuv build\n```\n\nThe screenshot helper is a separate Python project:\n\n```bash\ncd sidecars/appletv-screenshot\nuv sync --locked\nuv run ruff check .\nuv run ruff format --check .\nuv run pyright\nuv run pytest\n```\n\nThe root package deliberately does not depend on or bundle `pymobiledevice3`.\n\n---\n\n## Live tests\n\nNormal tests use fakes and do not require Apple hardware.\n\nRead-only Apple TV integration tests are explicitly opt-in:\n\n```bash\nAPPLE_TV_INTEGRATION_TESTS=1 uv run pytest -m live\n```\n\nTests that can change Apple TV state require an additional opt-in:\n\n```bash\nAPPLE_TV_INTEGRATION_TESTS=1 \\\nAPPLE_TV_LIVE_WRITES=1 \\\nuv run pytest -m live\n```\n\nNever enable the live-write suite against a device you do not intend to control.\n\n---\n\n## Contributing\n\nContributions are welcome.\n\nBefore opening a pull request:\n\n```bash\nuv run ruff check .\nuv run ruff format --check .\nuv run pyright\nuv run pytest\nuv build\n```\n\nIf your change affects the screenshot helper, run its independent quality gate as well.\n\nPlease preserve the project's core architecture:\n\n```text\ncontrol      = pyatv\nobservation  = external screenshot helper\nMCP          = semantic interface presented to the agent\n```\n\nAvoid exposing raw Apple protocol details through the MCP contract unless there is a clear semantic reason.\n\n---\n\n## License\n\nThis repository contains two separately distributed components.\n\n### Apple TV MCP\n\n`appletv-mcp` is licensed under the MIT License.\n\nIt does not import, bundle, or distribute `pymobiledevice3`.\n\n### Apple TV Screenshot\n\nThe optional `appletv-screenshot` helper under\n`sidecars/appletv-screenshot/` is licensed under GPL-3.0-or-later.\n\nThe helper directly uses `pymobiledevice3`, which is also licensed\nunder GPL-3.0-or-later.\n\nThe two components communicate through a one-shot subprocess interface.\n\nSee [`LICENSING.md`](LICENSING.md) for the repository-wide map.\n\n---\n\n## Built for a simple idea\n\nAI agents are much more useful when they can verify the effects of their actions.\n\nApple TV MCP gives them both sides of that loop:\n\n```text\ncontrol the Apple TV\n        +\nsee the Apple TV\n```\n\nSo instead of blindly pressing buttons, an agent can interact with tvOS, inspect the result, and decide what to do next.\n",
  "bytes": 18252,
  "sha": "6e8acda95ea2ee2e74ba2245bc4600e7e7e5f4bde70230ff5ed4bf87847cff56",
  "repo_slug": "trevor-nichols/appletv-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_trevor_nichols_appletv_mcp_cb72ec51/readme"
}