Roku Channel Operations
Unified workflow capability for Roku channel teams. Combines the External Control Protocol (local-network device control), Roku Pay Web Services (entitlement validation, refunds, subscriptions), and Roku Nabu Cloud (remote test devices, snapshots, builds) into a single REST and MCP surface. Personas: channel developer, QA engineer, billing operator.
What You Can Do
MCP Tools
ecp-get-device-info
Get Roku device metadata via ECP.
ecp-list-installed-apps
List channels installed on the local Roku device.
ecp-get-active-app
Get the active channel on the device.
ecp-get-media-player-state
Get the video player state.
ecp-launch-app
Launch an installed channel with optional deep-link.
ecp-press-key
Send a remote-control key press to the device.
ecp-exit-app
Suspend or terminate a running channel.
ecp-query-chanperf
Get channel CPU and memory metrics (developer mode).
pay-validate-transaction
Validate a Roku Pay transaction and return entitlement state.
pay-validate-refund
Confirm a Roku Pay refund.
pay-cancel-subscription
Cancel a Roku Pay subscription.
pay-refund-subscription
Refund a Roku Pay subscription.
pay-update-bill-cycle
Adjust the next billing date on a subscription.
pay-issue-service-credit
Issue an account-level service credit.
nabu-list-test-devices
List Nabu Cloud test devices in a project.
nabu-create-test-device
Allocate a Nabu Cloud test device.
nabu-start-test-device
Start a Nabu Cloud test device run.
nabu-stop-test-device
Stop a Nabu Cloud test device run.
nabu-read-test-device-logs
Read logs from a Nabu Cloud test device run.
nabu-list-builds
List channel builds in Nabu Cloud.
nabu-get-build
Get a Nabu Cloud build by id.
Capability Spec
naftiko: 1.0.0-alpha2
info:
label: Roku Channel Operations
description: 'Unified workflow capability for Roku channel teams. Combines the External Control Protocol
(local-network device control), Roku Pay Web Services (entitlement validation, refunds,
subscriptions), and Roku Nabu Cloud (remote test devices, snapshots, builds) into a single
REST and MCP surface. Personas: channel developer, QA engineer, billing operator.
'
tags:
- Roku
- Streaming
- Channel Development
- Test Automation
- Monetization
created: '2026-05-05'
modified: '2026-05-06'
binds:
- namespace: env
keys:
ROKU_DEVICE_IP: ROKU_DEVICE_IP
ROKU_PAY_PARTNER_API_KEY: ROKU_PAY_PARTNER_API_KEY
ROKU_NABU_CLOUD_TOKEN: ROKU_NABU_CLOUD_TOKEN
capability:
consumes:
- type: http
namespace: roku-ecp
baseUri: http://{{ROKU_DEVICE_IP}}:8060
description: Roku device on the local network.
resources:
- name: discovery
path: /
description: SSDP device description and metadata.
operations:
- name: get-device-root
method: GET
path: /
description: Returns the SSDP device description XML.
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- name: query-device-info
method: GET
path: /query/device-info
description: Returns device metadata (model, serial, software version, network state).
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- name: apps
path: /query/apps
description: Installed channel listing and active-app queries.
operations:
- name: query-apps
method: GET
path: /query/apps
description: Lists channels installed on the device.
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- name: query-active-app
method: GET
path: /query/active-app
description: Returns the currently active channel.
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- name: query-app-icon
method: GET
path: /query/icon/{appId}
description: Returns the binary icon image for the specified channel.
inputParameters:
- name: appId
in: path
type: string
required: true
description: Roku channel/app identifier.
outputRawFormat: binary
outputParameters:
- name: result
type: object
value: $.
- name: launch-app
method: POST
path: /launch/{appId}
description: Launches an installed channel; supports deep-link contentId/mediaType.
inputParameters:
- name: appId
in: path
type: string
required: true
description: Roku channel/app identifier.
- name: contentId
in: query
type: string
required: false
description: Deep-link content identifier.
- name: mediaType
in: query
type: string
required: false
description: Deep-link content type.
outputParameters:
- name: result
type: object
value: $.
- name: install-app
method: POST
path: /install/{appId}
description: Opens the channel store details page for the specified channel.
inputParameters:
- name: appId
in: path
type: string
required: true
description: Roku channel/app identifier.
outputParameters:
- name: result
type: object
value: $.
- name: exit-app
method: POST
path: /exit-app/{appId}
description: Suspends or terminates a running channel (Roku OS 14.1+).
inputParameters:
- name: appId
in: path
type: string
required: true
description: Roku channel/app identifier.
outputParameters:
- name: result
type: object
value: $.
- name: keypress
path: /keypress
description: Simulated remote-control key injection.
operations:
- name: key-press
method: POST
path: /keypress/{key}
description: Press-and-release a remote-control key.
inputParameters:
- name: key
in: path
type: string
required: true
description: Key name (Home, Up, Down, Left, Right, Select, Back, Play, etc.) or Lit_<char> for a literal character.
outputParameters:
- name: result
type: object
value: $.
- name: key-down
method: POST
path: /keydown/{key}
description: Press and hold a remote-control key.
inputParameters:
- name: key
in: path
type: string
required: true
description: Key name.
outputParameters:
- name: result
type: object
value: $.
- name: key-up
method: POST
path: /keyup/{key}
description: Release a previously held key.
inputParameters:
- name: key
in: path
type: string
required: true
description: Key name.
outputParameters:
- name: result
type: object
value: $.
- name: media-player
path: /query/media-player
description: Active video player playback state.
operations:
- name: query-media-player
method: GET
path: /query/media-player
description: Returns playback state, position, duration, and buffering metrics.
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- name: diagnostics
path: /query
description: Developer-mode diagnostics (chanperf, sgnodes, registry).
operations:
- name: query-chanperf
method: GET
path: /query/chanperf
description: CPU and memory metrics for the foreground channel.
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- name: query-sgnodes-all
method: GET
path: /query/sgnodes/all
description: All SceneGraph nodes with reference counts.
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- name: query-registry
method: GET
path: /query/registry/{appId}
description: Persistent registry entries for the specified channel.
inputParameters:
- name: appId
in: path
type: string
required: true
description: Roku channel identifier.
outputRawFormat: xml
outputParameters:
- name: result
type: object
value: $.
- type: http
namespace: roku-pay
baseUri: https://apipub.roku.com/listen/transaction-service.svc
description: Roku Pay production transaction service.
authentication:
type: apikey
key: partnerAPIKey
value: '{{ROKU_PAY_PARTNER_API_KEY}}'
placement: query
resources:
- name: validation
path: /validate-transaction
description: Transaction and refund validation.
operations:
- name: validate-transaction
method: GET
path: /validate-transaction/{partnerAPIKey}/{transactionId}
description: Verifies a customer's entitlement to a Roku Pay-purchased product.
inputParameters:
- name: partnerAPIKey
in: path
type: string
required: true
description: Roku-issued partner API key.
- name: transactionId
in: path
type: string
required: true
description: Transaction identifier returned by ChannelStore.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: validate-refund
method: GET
path: /validate-refund/{partnerAPIKey}/{refundId}
description: Confirms a refund has been issued.
inputParameters:
- name: partnerAPIKey
in: path
type: string
required: true
description: Roku-issued partner API key.
- name: refundId
in: path
type: string
required: true
description: Roku-issued refund identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: subscription
path: /cancel-subscription
description: Subscription lifecycle management.
operations:
- name: cancel-subscription
method: POST
path: /cancel-subscription
description: Cancels a Roku Pay subscription.
body:
type: json
data:
partnerAPIKey: '{{ROKU_PAY_PARTNER_API_KEY}}'
rokuCustomerId: '{{tools.rokuCustomerId}}'
productCode: '{{tools.productCode}}'
reason: '{{tools.reason}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: refund-subscription
method: POST
path: /refund-subscription
description: Issues a partial or full refund against a subscription.
body:
type: json
data:
partnerAPIKey: '{{ROKU_PAY_PARTNER_API_KEY}}'
rokuCustomerId: '{{tools.rokuCustomerId}}'
transactionId: '{{tools.transactionId}}'
refundAmount: '{{tools.refundAmount}}'
currency: '{{tools.currency}}'
reason: '{{tools.reason}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: update-bill-cycle
method: POST
path: /update-bill-cycle
description: Adjusts the next billing date on an active subscription.
body:
type: json
data:
partnerAPIKey: '{{ROKU_PAY_PARTNER_API_KEY}}'
rokuCustomerId: '{{tools.rokuCustomerId}}'
productCode: '{{tools.productCode}}'
nextBillDate: '{{tools.nextBillDate}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: issue-service-credit
method: POST
path: /issue-service-credit
description: Grants an account-level service credit to the customer.
body:
type: json
data:
partnerAPIKey: '{{ROKU_PAY_PARTNER_API_KEY}}'
rokuCustomerId: '{{tools.rokuCustomerId}}'
amount: '{{tools.amount}}'
currency: '{{tools.currency}}'
reason: '{{tools.reason}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- type: http
namespace: roku-nabu-cloud
baseUri: https://api.cloud.roku.dev
description: Roku Nabu Cloud production API.
authentication:
type: bearer
token: '{{ROKU_NABU_CLOUD_TOKEN}}'
resources:
- name: health
path: /api/v1/-
description: Service health endpoints.
operations:
- name: livez
method: GET
path: /api/v1/-/livez
description: Liveness probe.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: readyz
method: GET
path: /api/v1/-/readyz
description: Readiness probe.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: users
path: /api/v1/users/me
description: Current user, organisations, projects, groups, and personal access tokens.
operations:
- name: get-me
method: GET
path: /api/v1/users/me
description: Returns the authenticated user.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: get-my-organisations
method: GET
path: /api/v1/users/me/organisations
description: Lists organisations the user belongs to.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: get-my-projects
method: GET
path: /api/v1/users/me/projects
description: Lists projects the user has access to.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: get-my-groups
method: GET
path: /api/v1/users/me/groups
description: Lists groups the user belongs to.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: list-personal-access-tokens
method: GET
path: /api/v1/users/me/personal_access_tokens
description: Lists the user's personal access tokens.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: create-personal-access-token
method: POST
path: /api/v1/users/me/personal_access_tokens
description: Creates a new personal access token.
body:
type: json
data:
name: '{{tools.name}}'
scopes: '{{tools.scopes}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: revoke-personal-access-token
method: DELETE
path: /api/v1/users/me/personal_access_tokens/{token_id}
description: Revokes a personal access token.
inputParameters:
- name: token_id
in: path
type: string
required: true
description: Token identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: builds
path: /api/v1/builds
description: Channel builds.
operations:
- name: list-builds
method: GET
path: /api/v1/builds
description: Lists all builds visible to the caller.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: get-build
method: GET
path: /api/v1/builds/{build_id}
description: Returns a single build by id.
inputParameters:
- name: build_id
in: path
type: string
required: true
description: Build identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: projects
path: /api/v1/organisations/{organisation_id}/projects
description: Project lifecycle inside an organisation.
operations:
- name: list-projects
method: GET
path: /api/v1/organisations/{organisation_id}/projects
description: Lists projects in an organisation.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: create-project
method: POST
path: /api/v1/organisations/{organisation_id}/projects
description: Creates a project.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
body:
type: json
data:
name: '{{tools.name}}'
description: '{{tools.description}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: get-project
method: GET
path: /api/v1/organisations/{organisation_id}/projects/{project_id}
description: Returns a single project.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: delete-project
method: DELETE
path: /api/v1/organisations/{organisation_id}/projects/{project_id}
description: Deletes a project.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: devices
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices
description: Remote test device lifecycle and runs.
operations:
- name: list-devices
method: GET
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices
description: Lists devices in a project.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: create-device
method: POST
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices
description: Allocates a new test device.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
body:
type: json
data:
name: '{{tools.name}}'
region: '{{tools.region}}'
model: '{{tools.model}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: get-device
method: GET
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}
description: Returns a single device.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
- name: device_id
in: path
type: string
required: true
description: Device identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: start-device
method: POST
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}/start
description: Starts a device run.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
- name: device_id
in: path
type: string
required: true
description: Device identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: stop-device
method: POST
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}/stop
description: Stops a device run.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
- name: device_id
in: path
type: string
required: true
description: Device identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: read-device-logs
method: GET
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}/logs/{instance_id}
description: Reads logs for a device run instance.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
- name: device_id
in: path
type: string
required: true
description: Device identifier.
- name: instance_id
in: path
type: string
required: true
description: Run instance identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: snapshots
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}/snapshots
description: Device snapshot management.
operations:
- name: list-snapshots
method: GET
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}/snapshots
description: Lists snapshots for a device.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
- name: device_id
in: path
type: string
required: true
description: Device identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: create-snapshot
method: POST
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}/snapshots
description: Creates a snapshot of a device.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
- name: device_id
in: path
type: string
required: true
description: Device identifier.
body:
type: json
data:
name: '{{tools.name}}'
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
- name: delete-snapshot
method: DELETE
path: /api/v1/organisations/{organisation_id}/projects/{project_id}/devices/{device_id}/snapshots/{snapshot_id}
description: Deletes a snapshot.
inputParameters:
- name: organisation_id
in: path
type: string
required: true
description: Organisation identifier.
- name: project_id
in: path
type: string
required: true
description: Project identifier.
- name: device_id
in: path
type: string
required: true
description: Device identifier.
- name: snapshot_id
in: path
type: string
required: true
description: Snapshot identifier.
outputRawFormat: json
outputParameters:
- name: result
type: object
value: $.
exposes:
- type: rest
port: 8080
namespace: roku-channel-operations-api
description: Unified REST API for Roku channel operations.
resources:
- path: /v1/devices
name: devices
description: Local device control via ECP.
operations:
- method: GET
name: get-device-info
description: Returns device metadata.
call: roku-ecp.query-device-info
outputParameters:
- type: object
mapping: $.
- method: GET
name: list-installed-apps
description: Lists installed channels on the device.
call: roku-ecp.query-apps
outputParameters:
- type: object
mapping: $.
- method: GET
name: get-active-app
description: Returns the currently active channel.
call: roku-ecp.query-active-app
outputParameters:
- type: object
mapping: $.
- method: GET
name: get-media-player-state
description: Returns video player state.
call: roku-ecp.query-media-player
outputParameters:
- type: object
mapping: $.
- method: POST
name: launch-app
description: Launches an installed channel with optional deep-link.
call: roku-ecp.launch-app
with:
appId: rest.appId
contentId: rest.contentId
mediaType: rest.mediaType
outputParameters:
- type: object
mapping: $.
- method: POST
name: press-key
description: Sends a remote-control key press.
call: roku-ecp.key-press
with:
key: rest.key
outputParameters:
- type: object
mapping: $.
- path: /v1/entitlements
name: entitlements
description: Roku Pay transaction validation.
operations:
- method: GET
name: validate-transaction
description: Validates a Roku Pay transaction.
call: roku-pay.validate-transaction
with:
partnerAPIKey: rest.partnerAPIKey
transactionId: rest.transactionId
outputParameters:
- type: object
mapping: $.
- method: GET
name: validate-refund
description: Validates a Roku Pay refund.
call: roku-pay.validate-refund
with:
partnerAPIKey: rest.partnerAPIKey
refundId: rest.refundId
outputParameters:
- type: object
mapping: $.
- path: /v1/subscriptions
name: subscriptions
description: Subscription lifecycle and billing.
operations:
- method: POST
name: cancel-subscription
description: Cancels a Roku Pay subscription.
call: roku-pay.cancel-subscription
outputParameters:
- type: object
mapping: $.
- method: POST
name: refund-subscription
description: Issues a subscription refund.
call: roku-pay.refund-subscription
outputParameters:
- type: object
mapping: $.
- method: POST
name: update-bill-cycle
description: Adjusts the subscription billing date.
call: roku-pay.update-bill-cycle
outputParameters:
- type: object
mapping: $.
- method: POST
name: issue-service-credit
description: Issues an account-level service credit.
call: roku-pay.issue-service-credit
outputParameters:
- type: object
mapping: $.
- path: /v1/test-devices
name: test-devices
description: Nabu Cloud remote test devices and runs.
operations:
- method: GET
name: list-test-devices
description: Lists Nabu Cloud test devices in a project.
call: roku-nabu-cloud.list-devices
with:
organisation_id: rest.organisation_id
project_id: rest.project_id
outputParameters:
- type: object
mapping: $.
- method: POST
name: create-test-device
description: Allocates a Nabu Cloud test device.
call: roku-nabu-cloud.create-device
with:
organisation_id: rest.organisation_id
project_id: rest.project_id
outputParameters:
- type: object
mapping: $.
- method: POST
name: start-test-device
description: Starts a remote test device run.
call: roku-nabu-cloud.start-device
with:
organisation_id: rest.organisation_id
project_id: rest.project_id
device_id: rest.device_id
outputParameters:
- type: object
mapping: $.
- method: POST
name: stop-test-device
description: Stops a remote test device run.
call: roku-nabu-cloud.stop-device
with:
organisation_id: rest.organisation_id
project_id: rest.project_id
device_id: rest.device_id
outputParameters:
- type: object
mapping: $.
- method: GET
name: read-test-device-logs
description: Reads logs from a test device run instance.
call: roku-nabu-cloud.read-device-logs
with:
organisation_id: rest.organisation_id
project_id: rest.project_id
device_id: rest.device_id
instance_id: rest.instance_id
outputParameters:
- type: object
mapping: $.
- path: /v1/builds
name: builds
description: Channel builds in Nabu Cloud.
operations:
- method: GET
name: list-builds
description: Lists channel builds.
call: roku-nabu-cloud.list-builds
outputParameters:
- type: object
mapping: $.
- method: GET
name: get-build
description: Returns a single build.
call: roku-nabu-cloud.get-build
with:
build_id: rest.build_id
outputParameters:
- type: object
mapping: $.
- type: mcp
port: 9090
namespace: roku-channel-operations-mcp
transport: http
description: MCP server for AI-assisted Roku channel development, QA, and billing workflows.
tools:
- name: ecp-get-device-info
description: Get Roku device metadata via ECP.
hints:
readOnly: true
openWorld: true
call: roku-ecp.query-device-info
outputParameters:
- type: object
mapping: $.
- name: ecp-list-installed-apps
description: List channels installed on the local Roku device.
hints:
readOnly: true
openWorld: true
call: roku-ecp.query-apps
outputParameters:
- type: object
mapping: $.
- name: ecp-get-active-app
description: Get the active channel on the device.
hints:
readOnly: true
openWorld: true
call: roku-ecp.query-active-app
outputParameters:
- type: object
mapping: $.
- name: ecp-get-media-player-state
description: Get the video player state.
hints:
readOnly: true
openWorld: true
call: roku-ecp.query-media-player
outputParameters:
- type: object
mapping: $.
- name: ecp-launch-app
description: Launch an installed channel with optional deep-link.
hints:
readOnly: false
destructive: false
idempotent: false
openWorld: true
call: roku-ecp.launch-app
with:
appId: tools.appId
contentId: tools.contentId
mediaType: tools.mediaType
outputParameters:
- type: object
mapping: $.
- name: ecp-press-k
# --- truncated at 32 KB (37 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/roku/refs/heads/main/capabilities/channel-operations.yaml