MCP debug_eval

Description

Evaluate an expression on the debugged Roku app, routing to CDP (Hermes/TypeScript) or DAP (BrightScript) depending on the session's active backend(s) and the optional runtime parameter.

On the BrightScript side this is NOT a plain expression evaluator: EXECUTE (the underlying device command) only accepts STATEMENTS and returns no value at all, so a bare "m.someField" is a device compile error. This tool implements assign-then-read under the hood (EXECUTE "rkeval = <expr>", then read rkeval back via VARIABLES) -- transparent to the caller, who just supplies a normal expression. Containers come back richer than a string form would allow: result.variables holds the full readback (the value itself plus, for a container, its typed children), while result.value/ result.type are a convenience for the common scalar case. result.value can be legitimately undefined for a SUCCESSFUL eval whose result has no on-wire value payload (e.g. Invalid, or an interface-only type) -- this is a normal outcome, not a failure. A failed eval never produces this shape at all: it fails the tool call instead (see the error codes below), so undefined here always means "the value has no wire payload for this type," never "something went wrong."

On the BrightScript side, expression is a statement fragment interpolated directly into an assignment (or a print statement, with print:true) -- it is NOT sandboxed or input-validated in any way. This is intentional: the tool's whole purpose is arbitrary debug-mode eval, so treat expression as trusted debug input, not as a value a caller needs to escape or sanitize.

Requires a stopped app on the BrightScript side (same precondition as debug_stacktrace/dap_variables) -- returns a typed NOT_STOPPED error with a remediation hint while running, UNLESS the session was created with autoStop:true, in which case this tool halts the app (every thread, including render and task threads) and waits before evaluating.

frameIndex folds in cdp_debugger_eval_frame's functionality for the TypeScript side (converted internally to the paused call frame's callFrameId) and gives BrightScript frame-scoped eval; it uses the same innermost-first indexing as debug_stacktrace/debug_state's callFrames on both sides. On the TypeScript side, omitting frameIndex routes through Runtime.evaluate instead, which works regardless of whether a cdpdebugger* tool has already touched the connection. Passing frameIndex while paused evaluates directly in that frame's scope instead, for access to its locals/closures.

print:true wraps the expression in BrightScript's own print statement instead of assigning/reading a value -- use this only when you want to see console output (readable via debug_console_read afterward), not obtain a value. BrightScript-only; rejected for a TypeScript-routed call.

Error codes this tool can return: NOTSTOPPED (BrightScript, app running, no autoStop), EVAL_FAILED (the device rejected the evaluated statement itself -- a compile or runtime error in expression), EVAL_TEMP_NOT_FOUND (the _rkeval readback was rejected; retry), NOT_PAUSED (TypeScript, frameIndex given but not paused), FRAME_OUT_OF_RANGE (frameIndex beyond the current call stack).

Required parameters:

  • expression (string): Expression to evaluate. TypeScript: any JS expression. BrightScript: any BRS
    expression, e.g. "m.top.children[0].text".

Optional parameters:

  • runtime ("typescript" | "brightscript"): Force a backend. Defaults to the session's own mode
    (cdp_only -> typescript, dap_only -> brightscript, unified -> typescript).
  • frameIndex (integer >= 0): Evaluate in a specific stack frame instead of the current/top one.
  • threadId (string): BrightScript-only. Namespaced thread id, e.g. "brs:0". Uses the session's
    default thread when omitted.
  • print (boolean): BrightScript-only. See above. Default false.
  • sessionId (string): Session id returned by debug_session_create. Uses the active session when
    omitted.

Aliases

Aliases: cdp_eval, cdp_debugger_eval_frame.

See also

Parameters

additionalProperties: false

NameTypeRequiredValues
expressionstringYes
runtime"typescript" | "brightscript"Noenum: "typescript", "brightscript"
frameIndexintegerNominimum: 0
threadIdstringNo
printbooleanNo
sessionIdstringNo

expression

Expression to evaluate

runtime

Force a backend

frameIndex

Evaluate in a specific stack frame

threadId

BrightScript-only: namespaced thread id, e.g. brs:0

print

BrightScript-only: wrap in print instead of reading a value

sessionId

Session id returned by debug_session_create


Did this page help you?