RokuHarness Server
БесплатноНе проверенEnables comprehensive Roku automated testing by combining WebDriver for UI state verification and ECP for device control, allowing validation of acceptance crit
Описание
Enables comprehensive Roku automated testing by combining WebDriver for UI state verification and ECP for device control, allowing validation of acceptance criteria through natural language queries.
README
A Model Context Protocol (MCP) server for comprehensive Roku automated testing. RokuHarness combines Roku WebDriver and ECP (External Control Protocol) to provide both UI state verification and device control - enabling true acceptance criteria validation, not just remote control simulation.
Why WebDriver vs ECP?
| Capability | ECP | WebDriver |
|---|---|---|
| Press remote buttons | ✅ | ✅ |
| Launch apps | ✅ | ✅ |
| Query UI elements | ❌ | ✅ |
| Verify text is on screen | ❌ | ✅ |
| Check element attributes | ❌ | ✅ |
| Get SceneGraph XML | ❌ | ✅ |
| Take screenshots | ❌ | ✅ |
| Validate acceptance criteria | ❌ | ✅ |
Bottom line: ECP can press buttons, WebDriver can verify what happens.
Architecture
Your Tests (via any MCP client)
↓
RokuHarness MCP Server (this project)
↓ (WebDriver HTTP API)
Roku WebDriver Server (from Roku's repo)
↓ (ECP + Debug APIs)
Roku Device (your sideloaded channel)
Key Point: The Roku WebDriver Server uses BOTH ECP (for control) and Roku's debug APIs (for UI verification). This MCP server provides a unified interface to both capabilities.
Prerequisites
1. Roku WebDriver Server
You need to download and run Roku's official WebDriver server:
# Clone Roku's automated testing repo
git clone https://github.com/rokudev/automated-channel-testing.git
cd automated-channel-testing
# Build the WebDriver server (requires Go)
cd src
go build
# Run the server
./RokuWebDriver # Linux/Mac
# or
RokuWebDriver.exe # Windows
The server will start on http://localhost:9000 by default.
Download pre-built binaries: Check the automated-channel-testing/bin folder for pre-compiled executables.
2. Sideloaded Channel
WebDriver requires your channel to be sideloaded in developer mode:
- Enable developer mode on your Roku: Settings → System → About → Press Home 5x, Up, Rewind 2x, Fast Forward 2x
- Package your channel as a
.zipfile - Visit
http://YOUR_ROKU_IPin a browser - Upload and install your channel
Important: WebDriver only works with:
- Sideloaded developer channels (app ID:
dev) - Channels packaged with your developer account on that specific device
- SceneGraph-based channels (not legacy BrightScript)
3. This MCP Server
npm install
npm run build
Installation & Setup
1. Build this MCP server
npm install
npm run build
2. Configure Your MCP Client
For Claude Desktop:
Add to claude_desktop_config.json:
{
"mcpServers": {
"rokuharness": {
"command": "node",
"args": ["/absolute/path/to/rokuharness-mcp/build/index.js"]
}
}
}
For Custom MCP Clients:
RokuHarness is MCP-agnostic and works with any MCP client. See "Using Without Claude Desktop" section below for integration examples.
3. Start the Roku WebDriver Server
In a separate terminal:
cd /path/to/automated-channel-testing/bin
./RokuWebDriver # or RokuWebDriver.exe on Windows
Keep this running while testing.
4. Restart Claude Desktop
The MCP server will now be available in Claude.
Usage Guide
Step 1: Create a Session
Every test session starts by creating a WebDriver session:
Create a Roku WebDriver session:
- WebDriver URL: http://localhost:9000
- Roku IP: 192.168.1.100
- App: dev
This connects to your sideloaded channel.
Step 2: Get UI Source (Critical!)
Before writing any verification queries, inspect the UI:
Get the UI source to see what elements are on screen
You'll get back SceneGraph XML like:
<Scene>
<Label id="titleLabel" text="Welcome to My App" focused="false" />
<Button id="loginButton" text="Log In" focused="true" />
<Poster id="heroImage" uri="https://..." />
</Scene>
This XML shows you:
- Tags: Component types (Label, Button, Poster, etc.)
- Attributes: Properties like
id,text,focused,visible - Hierarchy: Nested structure
Step 3: Verify Elements
Now you can write acceptance criteria tests:
Verify that a Label with text "Welcome to My App" is present on screen
Verify that a Button with id "loginButton" and focused=true is present
Verify that the login button text says "Log In"
Step 4: Navigate and Test
Navigate using these keys: ["Down", "Down", "Select"]
Then verify that a Label with text "Account Settings" appears
Step 5: Run Complete Test Scenarios
Run this acceptance test:
Test: Login Flow
Steps:
1. Press Select to click login button
2. Verify keyboard screen appears (look for Label with text "Enter Email")
3. Send text "[email protected]"
4. Press Down to go to password field
5. Send text "password123"
6. Press Select to submit
7. Verify success message appears
8. Take screenshot
Available Tools
Session Management
create_webdriver_session
Creates a new WebDriver session.
Parameters:
webdriver_url(optional): URL of WebDriver server (default: http://localhost:9000)roku_ip(required): IP address of Roku deviceapp(optional): App ID or "dev" for sideloaded (default: "dev")
Example:
Create a WebDriver session for Roku at 192.168.1.100
end_webdriver_session
Ends the current session and cleans up.
UI State Verification (The Key Features!)
get_ui_source
Get the current UI hierarchy as XML or JSON.
Parameters:
parsed(optional): Return JSON instead of XML
Example:
Get the UI source to see current screen structure
Returns:
<Scene>
<LayoutGroup id="mainLayout">
<Label id="title" text="Home Screen" />
<Button id="playButton" text="Play" focused="true" />
</LayoutGroup>
</Scene>
This is essential for understanding what elements exist and how to query them.
find_element
Search for a specific element on screen.
Parameters:
text(optional): Text content to matchtag(optional): SceneGraph component typeattributes(optional): Attribute key-value pairs
Examples:
Find a Label with text "Home Screen"
Find a Button with id "playButton"
Find an element with tag "Poster" and attribute uri="https://example.com/image.jpg"
verify_element_present
Check if an element exists (returns true/false).
Parameters:
- Same as
find_element timeout_ms(optional): How long to wait (default: 10000)
Examples:
Verify a Label with text "Loading..." is present
Check if login button is focused: Button with focused=true
verify_screen_loaded
Wait for a specific screen to fully load.
Parameters:
screen_marker: Element query that identifies the screentimeout_ms(optional): Maximum wait time
Example:
Verify the home screen loaded by checking for Label with text "Featured Content"
Navigation & Input
press_key
Press a single remote button.
Parameters:
key: Button name (Home, Back, Up, Down, Left, Right, Select, Play, Pause, etc.)
navigate
Execute a sequence of button presses.
Parameters:
keys: Array of keys to pressdelay_ms(optional): Delay between presses
Example:
Navigate: Down, Down, Right, Select with 750ms delays
send_text
Send text input (for keyboards/forms).
Parameters:
text: Text to type
Media & Apps
launch_app
Launch an app with optional deep linking.
Parameters:
app_id: App ID ("dev" for sideloaded)content_id(optional): Deep link content IDmedia_type(optional): Type (movie, series, etc.)
get_player_state
Get current playback state.
Returns: Position, duration, state, buffering info
get_installed_apps
List all installed apps.
Screenshots
take_screenshot
Capture current screen.
Parameters:
save_path(optional): Where to save the image
Example:
Take a screenshot and save to /tmp/login_screen.png
Acceptance Testing
run_acceptance_test
Execute a complete test case with multiple steps.
Parameters:
test_name: Name of the teststeps: Array of test steps
Step types:
navigate: Execute key sequenceverify_element: Check element is presentpress_key: Press single keysend_text: Type textwait: Pause for durationscreenshot: Capture screen
Example:
Run this acceptance test:
Name: "Video Playback Test"
Steps:
1. Action: navigate, Keys: ["Down", "Down", "Select"], Description: "Select first video"
2. Action: verify_element, Query: {tag: "Video", attributes: {state: "playing"}}, Description: "Verify video is playing"
3. Action: wait, Duration: 5000, Description: "Let video play for 5 seconds"
4. Action: press_key, Key: "Pause", Description: "Pause playback"
5. Action: verify_element, Query: {tag: "Video", attributes: {state: "paused"}}, Description: "Verify video paused"
6. Action: screenshot, Description: "Capture paused state"
Element Query Syntax
Elements are queried using combinations of:
By Text
{ "text": "Log In" }
Finds elements containing this exact text.
By Tag
{ "tag": "Button" }
Finds elements of this SceneGraph type.
Common tags:
Label- Text displayButton- Interactive buttonPoster- ImageVideo- Video playerLayoutGroup- ContainerRowList- Scrollable listGrid- Grid layout
By Attributes
{
"attributes": {
"id": "loginButton",
"focused": "true"
}
}
Common attributes:
id- Unique identifierfocused- Has focus (true/false)visible- Is visible (true/false)text- Text contenturi- Image/video URI
Combined Queries
{
"tag": "Button",
"text": "Log In",
"attributes": {
"focused": "true"
}
}
Finds a Button with text "Log In" that currently has focus.
Real-World Examples
Example 1: Validate Login Screen
1. Create WebDriver session for Roku at 192.168.1.100
2. Get UI source to inspect elements
3. Verify these elements are present:
- Label with text "Sign In"
- Button with text "Email Login"
- Button with text "Guest Mode"
4. Take screenshot for documentation
Example 2: Test Video Playback
Run this acceptance test:
Name: "Video Playback Verification"
Steps:
1. Navigate to content: ["Down", "Down", "Select"]
2. Verify video player loaded: tag=Video
3. Wait 3 seconds for playback to start
4. Verify video is playing: tag=Video, attributes={state: "playing"}
5. Press "Info" to show controls
6. Verify play/pause button visible: tag=Button, text="Pause"
7. Take screenshot of player controls
Example 3: Search Functionality
Test search feature:
1. Press "Search" key
2. Verify keyboard screen: Label with text "Search"
3. Send text "Breaking Bad"
4. Press "Select" to submit
5. Verify results loaded: Label with text "Results for: Breaking Bad"
6. Verify at least one result: tag=Poster (poster images indicate results)
Example 4: Settings Navigation
Navigate to settings and verify:
1. Press Home
2. Navigate: ["Down", "Down", "Down", "Right", "Right", "Select"]
3. Verify settings screen: Label with text "Settings"
4. Navigate: ["Down", "Select"]
5. Verify account screen: Label with text "Account Information"
6. Get UI source to document screen structure
Troubleshooting
"No active session"
You must call create_webdriver_session before any other commands.
"WebDriver server not responding"
Ensure the Roku WebDriver server is running:
./RokuWebDriver
"Element not found"
- Get the UI source first:
get_ui_source - Inspect the actual XML structure
- Adjust your query to match actual elements
- Check spelling and capitalization (XML is case-sensitive)
"Cannot get source from channel"
- Only works with sideloaded channels or channels packaged on that device
- Production channels block source access (security feature)
- Make sure your channel is running (not on Home screen)
Screenshots not working
Screenshots only work when:
- Your sideloaded channel is active
- Developer mode is enabled
- WebDriver has proper access
Slow queries
- WebDriver queries can take 500ms-2s depending on complexity
- Use specific queries (tag + attributes) for faster results
- Avoid overly broad queries
Roku WebDriver Limitations
- Sideloaded channels only - Production channels block UI introspection
- SceneGraph only - Legacy BrightScript channels not supported
- No visual comparisons - You get XML structure, not rendered pixels
- Element bounds are relative - Absolute position checking is complex
- No direct element interaction - You still navigate with D-pad, not clicks
Best Practices
1. Always Inspect First
Get UI source → Understand structure → Write queries
2. Use Specific Queries
❌ { "text": "Play" } // Might match multiple elements
✅ { "tag": "Button", "id": "mainPlayButton", "text": "Play" }
3. Wait for Screens to Load
verify_screen_loaded with appropriate timeout
4. Test One Thing at a Time
Break complex flows into individual test cases.
5. Take Screenshots
Document state before/after critical steps.
6. Use Acceptance Test Tool
For multi-step scenarios, use run_acceptance_test to get structured results.
Integration with CI/CD
This MCP server can be integrated into CI/CD pipelines:
- Provision Roku devices in your test lab
- Start WebDriver server on each
- Run tests via MCP server
- Collect results and screenshots
- Publish test reports
Using Without Claude Desktop
RokuHarness is built on the open MCP standard and works with any MCP client. Here are integration examples:
Python CI/CD Integration
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
# Connect to RokuHarness MCP server
server_params = StdioServerParameters(
command="node",
args=["/path/to/rokuharness-mcp/build/index.js"]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# Create WebDriver session
result = await session.call_tool(
"create_webdriver_session",
arguments={
"roku_ip": "192.168.1.100",
"app": "dev"
}
)
# Get UI source
ui_source = await session.call_tool("get_ui_source", {})
# Verify element
verify_result = await session.call_tool(
"verify_element_present",
arguments={
"text": "Welcome",
"tag": "Label"
}
)
# Assert in your test framework
assert verify_result["present"] == True
# Run acceptance test
test_result = await session.call_tool(
"run_acceptance_test",
arguments={
"test_name": "Login Flow",
"steps": [
{
"action": "navigate",
"description": "Go to login",
"keys": ["Down", "Down", "Select"]
},
{
"action": "verify_element",
"description": "Check login screen",
"element_query": {"text": "Sign In"}
}
]
}
)
print(f"Test Status: {test_result['summary']['status']}")
Node.js Integration
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
const transport = new StdioClientTransport({
command: 'node',
args: ['/path/to/rokuharness-mcp/build/index.js']
});
const client = new Client({
name: 'roku-test-runner',
version: '1.0.0'
}, {
capabilities: {}
});
await client.connect(transport);
// Create session
const session = await client.request({
method: 'tools/call',
params: {
name: 'create_webdriver_session',
arguments: {
roku_ip: '192.168.1.100',
app: 'dev'
}
}
});
// Verify element
const result = await client.request({
method: 'tools/call',
params: {
name: 'verify_element_present',
arguments: {
tag: 'Button',
text: 'Play'
}
}
});
console.log('Element present:', result.present);
Integration Points
✅ CI/CD Pipelines - Jenkins, GitHub Actions, GitLab CI, CircleCI
✅ Test Frameworks - Jest, Mocha, Pytest, JUnit
✅ QA Platforms - TestRail, Zephyr, qTest, Xray
✅ Custom Dashboards - Build your own test runner UI
✅ Scheduled Testing - Cron jobs, AWS Lambda, Azure Functions
✅ Any MCP-compatible tool - The protocol is completely open
Example GitHub Actions Workflow
name: Roku UI Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: |
cd rokuharness-mcp
npm install
npm run build
- name: Start Roku WebDriver Server
run: |
wget https://github.com/rokudev/automated-channel-testing/releases/download/v1.0/RokuWebDriver
chmod +x RokuWebDriver
./RokuWebDriver &
- name: Run tests
run: python tests/run_roku_tests.py
env:
ROKU_IP: ${{ secrets.ROKU_IP }}
- name: Upload screenshots
if: always()
uses: actions/upload-artifact@v3
with:
name: test-screenshots
path: screenshots/
Comparison with Other Tools
vs Roku Robot Framework
- This: Natural language via Claude, MCP protocol
- Robot: Keyword-driven, separate test files
vs Appium Roku Driver
- This: Direct WebDriver access, simpler setup
- Appium: Appium ecosystem integration, more tooling
vs Manual Testing
- This: Automated, repeatable, fast
- Manual: Comprehensive but slow, expensive
Resources
- Roku WebDriver Documentation
- Automated Channel Testing Repo
- SceneGraph XML Reference
- Roku Developer Portal
Support
For issues or questions:
- Roku WebDriver: Roku Community Forums
- This MCP Server: Open an issue in this repository
- Claude/MCP: Anthropic Documentation
License
MIT License - Free to use for your Roku testing needs.
Установка RokuHarness Server
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/miabilabs/rokuharness-mcpFAQ
RokuHarness Server MCP бесплатный?
Да, RokuHarness Server MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для RokuHarness Server?
Нет, RokuHarness Server работает без API-ключей и переменных окружения.
RokuHarness Server — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить RokuHarness Server в Claude Desktop, Claude Code или Cursor?
Открой RokuHarness Server на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
LibreOffice Tools
Enables AI agents to read, write, and edit Office documents via LibreOffice with token-efficient design. Supports multiple formats including DOCX, XLSX, PPTX, a
автор: passerbyflutterdannote/figma-use
Full Figma control: create shapes, text, components, set styles, auto-layout, variables, export. 80+ tools.
автор: dannoteLogo.dev
Search and retrieve company logos by brand or domain. Customize size, format, and theme to match your design needs. Accelerate design, prototyping, and content
автор: NOVA-3951PIX4Dmatic
Enables GUI automation for controlling PIX4Dmatic on Windows through MCP. Supports launching, focusing, capturing screenshots, sending hotkeys, clicking UI elem
автор: jangjo123Compare RokuHarness Server with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории design
