An autonomous Model Context Protocol (MCP) server that empowers AI coding agents (such as Antigravity, Claude, and Cursor) to develop, deploy, navigate, inspect, and debug Roku BrightScript and SceneGraph applications.
Roku OS separates development APIs across four distinct network protocols on four different ports. roku-dev-mcp acts as a middleware controller that bridges the agent's structured JSON tool-call interface and Roku's fragmented developer API surface.
┌──────────────────────────────────────────────────────────────────┐
│ MCP Client (Agent) │
│ (Antigravity / Claude / etc.) │
└──────────────────────────┬───────────────────────────────────────┘
│ MCP Protocol (stdio)
▼
┌──────────────────────────────────────────────────────────────────┐
│ roku-dev-mcp Server │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────────────────┐ │
│ │ Tool Router │ │ Log Buffer │ │ Connection Manager │ │
│ │ (Zod Schemas│ │ (Ring Buffer │ │ (Mutex, Reconnect, │ │
│ │ & Handlers)│ │ & Crash Det)│ │ Timeouts) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬─────────────────┘ │
│ │ │ │ │
│ ┌──────┴─────────────────┴──────────────────┴─────────────────┐ │
│ │ Roku Interface Adapters │ │
│ │ ┌─────────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │ │
│ │ │ Port 80 │ │ Port │ │ Port │ │ Port 8085 │ │ │
│ │ │ Installer │ │ 8060 ECP │ │ 8080 SG │ │ BS Console │ │ │
│ │ │ (HTTP/ │ │ (HTTP │ │ Debug │ │ (Telnet / │ │ │
│ │ │ Digest) │ │ REST) │ │ (Telnet) │ │ Persistent)│ │ │
│ │ └──────┬──────┘ └────┬─────┘ └────┬─────┘ └──────┬──────┘ │ │
│ └─────────┼─────────────┼────────────┼──────────────┼──────────┘ │
└────────────┼─────────────┼────────────┼──────────────┼────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────────────────────────────────────────────────────────┐
│ Roku Device (TV / Stick) │
│ :80 Installer :8060 ECP :8080 SG Debug :8085 BS Debug │
└──────────────────────────────────────────────────────────────────┘
| Port | Protocol | Auth | Connection | Purpose |
|---|---|---|---|---|
| 80 | HTTP | Digest (rokudev / password) |
Per-request | Sideloading (/plugin_install), screenshot capture (/plugin_inspect) |
| 8060 | HTTP REST | None* | Per-request | Remote keypresses, deep linking, device/media state queries |
| 8080 | Telnet (TCP) | None | On-demand (Serialized) | SceneGraph live node tree dumps (sgnodes all) |
| 8085 | Telnet (TCP) | None | Persistent background | BrightScript console logs, real-time crash capture, interactive debugger |
When several local MCP clients target the same Roku, they coordinate their BrightScript-console connection automatically. Only one local instance connects to port 8085; the others receive its log stream over a local IPC socket.
*Requires "Control by mobile apps" enabled in Roku OS 14.1+.
- Developer Mode enabled:
- Remote sequence:
Home ×3 → Up ×2 → Right → Left → Right → Left → Right. - Set a developer password (used as
ROKU_DEV_PASSWORD).
- Remote sequence:
- "Control by mobile apps" enabled:
Settings → System → Advanced system settings → Control by mobile apps→ select "Enabled".
- Local Network Connectivity:
- Ensure the host machine running the MCP server is on the same subnet as the Roku device.
- Ports
80,8060,8080, and8085must be accessible.
- Node.js:
≥ 20.0.0(LTS recommended) - npm or pnpm
Create a .env file in the project root or configure environment variables in your MCP client:
| Variable | Required | Default | Description |
|---|---|---|---|
ROKU_DEV_PASSWORD |
Yes | — | Developer password set during Developer Mode activation. |
ROKU_DEVICE_IP |
No | SSDP discovery | IPv4 address of the target Roku device (e.g. 192.168.1.50). |
ROKU_LOG_BUFFER_SIZE |
No | 500 |
Max lines in the BrightScript ring buffer. |
ROKU_KEYPRESS_DELAY_MS |
No | 100 |
Delay in milliseconds between sequential keypresses. |
ROKU_CONNECT_TIMEOUT_MS |
No | 5000 |
TCP connection timeout for Telnet sockets. |
ROKU_COMMAND_TIMEOUT_MS |
No | 10000 |
Telnet command execution timeout. |
Add the server to your MCP client configuration (e.g., mcpServers in claude_desktop_config.json or Antigravity MCP settings):
{
"mcpServers": {
"roku-dev": {
"command": "node",
"args": ["/absolute/path/to/roku-dev-mcp/dist/index.js"],
"env": {
"ROKU_DEV_PASSWORD": "your_roku_dev_password",
"ROKU_DEVICE_IP": "192.168.1.50"
}
}
}
}For detailed configuration instructions for Antigravity, Claude CLI / Claude Desktop, Codex, and Opencode, see docs/INSTALL.md.
Runs the project's build script with the detected package manager (npm, pnpm, or yarn) and returns its Roku ZIP artifact. If the build produces more than one ZIP, provide package_path to select one.
Validates and sideloads a pre-built Roku ZIP. The archive must have manifest at its root; it can be produced by BrighterScript, roku-deploy, or any other build system.
Legacy convenience tool that zips a BrightScript/SceneGraph project directory and sideloads the raw source. Prefer roku_build then roku_deploy for projects with a build step, because compiled/transformed sources must come from the build artifact.
- Inputs:
source_dir(string): Absolute path to project root (must containmanifest).action("Install" | "Replace", default:"Install"): Install replaces any existing sideloaded app.exclude_patterns(string[], optional): Additional glob patterns to exclude.
- Returns: Deployment result, startup logs, install duration, and crash status.
Sends sequential ECP keypress commands with configurable inter-key delays.
- Inputs:
keys(string[]): Ordered list of ECP keys (e.g.["Home", "Down", "Select", "Lit_a"]).delay_ms(number, optional): Delay between keypresses in milliseconds.
- Returns: Keys sent count, execution duration, and errors if any.
Inspects and parses the live SceneGraph node tree into a JSON tree structure.
- Inputs:
filter_id(string, optional): Subtree root node ID.include_fields(boolean, default:true): Include node field key-values.max_depth(number, optional): Maximum tree depth.
- Returns: Parsed node tree with reference counts and field data.
Produces a composite multi-modal snapshot of the device state.
- Inputs:
log_lines(number, default:50): Recent BrightScript log entries.include_screenshot(boolean, default:true): Base64 screenshot image.include_ui_tree(boolean, default:false): SceneGraph tree snapshot.
- Returns: Composite JSON state plus inline image payload for multimodal agents.
Queries ECP media player to verify video playback state and metrics.
- Inputs: None.
- Returns:
is_playing,is_buffering,progress_percent, duration, stream bitrate, and audio/video formats.
Deterministic condition-based polling to avoid hardcoded sleep timers.
- Inputs:
condition(string): Condition expression (node_exists: {id},node_field: {id}.{field}={val},playback_state: {state},app_active: {id},log_contains: {pattern},crash_detected).timeout_seconds(number, default:10): Max wait duration.poll_interval_ms(number, default:500): Polling interval.
- Returns: Satisfaction flag, elapsed time, poll count, and matched snapshot.
Deep-links into specific content items within the sideloaded application.
- Inputs:
content_id(string, optional): Target content ID.media_type(string, optional): Media type hint (movie,series, etc.).params(Record<string, string>, optional): Extra query parameters.
- Returns: Launch confirmation and active app verification.
# Install dependencies
npm install
# Run unit tests (uses built-in MockRokuDevice)
npm test
# Run unit tests specifically
npm run test:unit
# Run integration tests against a real Roku TV
npm run test:integration
# Run all tests (unit + integration)
ROKU_INTEGRATION_TEST=1 npm test
# Run build
npm run buildFor full testing documentation and step-by-step verification instructions, refer to docs/TESTING.md.
This project is licensed under the Unlicense — public domain.