MCP methods
Kasm Session Runtime serves 28 methods over the Model Context Protocol (MCP) when it runs as kasm-session-runtime mcp. An outside agent, such as Claude Code, Codex or any other MCP client, uses them to drive the desktop directly. In this mode there is no scenario and the runtime reaches no verdict; the loop is your agent’s. The same methods are available without MCP as plain HTTP calls at POST /v1/call/<method> (see HTTP API).
Most of these methods need no model in the runtime. Three of them, screen.judge, screen.ground and screen.ask, call the vision model configured in KASM_RUNTIME_VISION_ENDPOINT. With no endpoint set, they return a resolution error and every other method works as normal. The “Model” column in each table below says which is which.
Every call is recorded as one row in report.json’s steps[] with "backend": "rpc", the same record a scripted run leaves.
Transports and credentials
Section titled “Transports and credentials”| stdio | Streamable HTTP | |
|---|---|---|
| When | the default | KASM_RUNTIME_SESSION_TOKEN is set |
| Wire | JSON-RPC 2.0, one message per line | MCP Streamable HTTP at /mcp, port KASM_SESSION_RUNTIME_PORT (default 9434) |
| Protocol version | initialize must send 2024-11-05 |
chosen per request by the Mcp-Protocol-Version header; 2026-07-28 and later are stateless, earlier versions use initialize and Mcp-Session-Id |
| Credential | none; the pipe is the trust boundary | the session token in the X-Kasm-Runtime-Session-Token header, 401 if missing or wrong |
| Typical caller | a client that starts kasm-session-runtime mcp as a subprocess inside the session |
a client outside the container, reaching the session through Kasm’s reverse proxy |
No method has a credential of its own; the transport’s credential covers every method.
The token goes in a custom header because Kasm’s port-map proxy overwrites Authorization before forwarding. Through Kasm, the address is https://<host>/desktop/<kasm_id>/mcp/mcp, where the first mcp is the port-map service name and the second is the runtime’s own path.
Calls are handled one at a time on both transports, and on HTTP a second call waits for the first to finish. The session has one display and one browser tab.
tools/list returns the 28 methods in sorted order, each with its JSON Schema. The server stays off unless the session is started with KASM_RUNTIME_SESSION_TOKEN; see Enable the runtime on a workspace.
Errors
Section titled “Errors”A method that fails returns a normal tools/call result with isError: true. The message starts with the method name and says what went wrong. Failures fall into three classes.
| Class | Meaning | What to do |
|---|---|---|
| Malformed | bad or missing parameters; the call never touched the session | fix the parameters and retry |
| Resolution | a capability is unavailable, something was not found, or a wait timed out | retry, try something else, or give up |
| Environment | the runtime itself is broken: X11 unreachable, a command that cannot start, the model erroring | not retryable |
Over /v1/call/, the class decides the HTTP status: malformed is 400, resolution 422, environment 500.
JSON-RPC protocol errors are used for unparsable input, unknown methods and shutdown. A call that arrives after the server has begun shutting down, or is still waiting its turn then, is refused with a JSON-RPC error whose message names “server shutting down” (code -32001 on stdio); that call never ran and records no step. A call already running when shutdown begins finishes and is recorded.
screen
Section titled “screen”| Method | Parameters | Returns | Model |
|---|---|---|---|
screen.capture |
none | {Width, Height, JPEGBase64}, at the size actually captured |
No |
screen.judge |
expectation (string, required) |
{Holds, Description} |
Yes |
screen.ground |
description (string, required) |
{Found, X, Y, Description} |
Yes |
screen.ask |
question (string, required) |
a plain-text answer | Yes |
windows.list |
none | the top-level X11 windows | No |
screen.capture,screen.ground,screen.askandwindows.listneed the X11 display; without it they return a resolution error (“no X connection”).- The three model methods return a resolution error when no endpoint is configured, or when the runtime has stopped calling the endpoint after repeated failures. An error from the model during the call is an environment error, except in
screen.ground, where a location the model cannot give is a resolution error. screen.groundreturns a location and does not click; pass itsXandYtoinput.click. They are screen pixels whatever answer convention the model uses. When the element is not visible it returnsFound: falsewith no point.screen.asksends the screenshot and, when available, text from the attached browser tab (title, URL, visible text, interactive elements) and the accessibility tree’s actionable elements.- The grounding accuracy the project has measured is for the Qwen3-VL family. For any other model,
screen.ground’s accuracy is unmeasured. See Vision models.
| Method | Parameters | Returns | Model |
|---|---|---|---|
input.key |
chord (string, required), e.g. "ctrl+s" |
"pressed <chord>" |
No |
input.click |
x, y (integers, required): root-window pixels |
"clicked (x, y)" |
No |
input.type |
exactly one of ref or text |
"typed N character(s)" |
No |
input.cursor |
none | {cursor} |
No |
input.wait_for |
exactly one of text, key or click; optional since, timeout_ms, origin |
{matched, captured, events, cursor, dropped} |
No |
input.key,input.clickandinput.typeneed the X display (resolution error without it). An input the X server does not accept is a resolution error. A non-integer or out-of-range coordinate is malformed.input.typerecords only the length of what it typed. See ref or literal.input.cursorandinput.wait_forneedKASM_RUNTIME_OBSERVE_INPUT=true. Without it they return a resolution error saying so.input.wait_forwaits for input the session receives from any source, the Kasm viewer included.clickis{button, x, y, radius}:buttondefaults to 1,radiusto 0, and leaving out bothxandymatches anywhere.timeout_msdefaults to 5000, at most 60000.originisexternal(the default: not the runtime’s own input),runtime(clicks only) orany.- On timeout
input.wait_forreturnsmatched: falsewith what was captured, without an error. Takeinput.cursorbefore acting and pass it assince, so input that arrives before the wait begins still matches.
Processes
Section titled “Processes”| Method | Parameters | Returns | Model |
|---|---|---|---|
proc.list |
match: substring of /proc/*/cmdline, "" for all |
the matching processes | No |
proc.spawn |
cmd (string, required) |
"spawned" |
No |
proc.kill |
match (required): a case-sensitive POSIX extended regular expression |
"sent" |
No |
launch |
cmd (required), env (object of strings, optional) |
"launched" |
No |
shell |
cmd (string, required) |
combined stdout and stderr | No |
wait_while |
kind (growing or process) and timeout_s (required); path or match; poll_s (default 0.5); quiet_polls (default 3) |
"quiesced" |
No |
- Processes start detached, as the session user.
launchalso records the process as the session’s launched app. - A command that cannot start is an environment error. A
proc.killpattern that does not compile is malformed. shellruns to completion. A nonzero exit is a resolution error;shfailing to start is an environment error.wait_whileholds until a growing file or directory stops changing size, or no process matches, forquiet_pollssamples in a row. Iftimeout_spasses first, it is a resolution error.growingneedspath;processneedsmatch.
These methods act on a browser tab over the Chrome DevTools Protocol (CDP). None needs a model.
| Method | Parameters | Returns |
|---|---|---|
dom.query |
selector (CSS, required) |
the element’s description and attributes |
dom.click |
selector (CSS, required) |
the element’s description |
dom.fill |
selector (required); exactly one of ref or value |
"filled <selector> (N character(s))" |
dom.wait |
predicate (JavaScript boolean, required), timeout_s |
"holds" |
dom.url |
none | the tab’s location.href |
dom.navigate |
url (required), timeout_s |
"navigated" |
dom.list_interactive |
filter (optional, case-insensitive substring) |
[{handle, role, name, disabled}, ...] |
dom.click_described |
description (required): a handle or the element’s text |
"clicked <name> (<role>)" |
- The runtime attaches to the browser on the first
dom.*call if it is not attached yet, diallingKASM_RUNTIME_CDP_ENDPOINT(defaulthttp://127.0.0.1:9222) for up to 5 seconds. A failed attach is a resolution error naming the cause; call again once the browser is up. The browser must be running with--remote-debugging-portand a--user-data-dir(see Compatibility). - The endpoint must be a loopback address unless
KASM_RUNTIME_CDP_ALLOW_REMOTE=true. - A missing required parameter is malformed. An element that is not found, a predicate that does not hold before
timeout_s, and a navigation that fails are resolution errors. dom.clickanddom.click_describeddeliver the click to the element, with no screen coordinates.
dom.list_interactive reads the page’s live accessibility tree and returns each interactive element with the text the page gives it, grouped by name, so a product row’s link, button and checkbox come back as one entry named by the row. Each entry has a five-character handle. Pass the handle to dom.click_described. A paraphrased name matches nothing.
A handle does not point at a page node. Passing one back matches the element’s name against a fresh read of the page. If the page has changed, the call returns a resolution error listing what is there now, and nothing is clicked. Matching tries the handle (exact only), then the exact name, then a unique substring. No match and more than one match are both resolution errors, and the error lists the candidates with their handles so the call can be retried. filter uses the same matching as dom.click_described, so any text a filter shows can be clicked as written.
These methods use the application’s accessibility tree over AT-SPI. They need no model.
| Method | Parameters | Returns |
|---|---|---|
a11y.tree |
none | {Status, Actionable: [...]}: the matched application’s actionable elements |
a11y.action |
name (required); expect_state; expect_value (boolean, default true) |
a description |
- The application is matched by the loaded scenario’s
window,processandapp, or byKASM_RUNTIME_APPwhen no scenario is loaded. a11y.actioninvokes the element’s default action. Withexpect_state, it waits for the screen to settle, reads the state back, and returns a resolution error if the state does not hold.- Both return a resolution error if the loaded scenario sets
atspi: false.
| Method | Parameters | Returns | Model |
|---|---|---|---|
file.get |
path |
{path, bytes, sha256, content_b64} |
No |
directory.get |
path |
{path, files, bytes, skipped, zip_bytes, sha256, zip_b64} |
No |
- A path is
~,~/<path>,/tmpor/tmp/<path>. An absolute path under the home directory is read as~/<path>. A path outside those roots, including one that leaves them through a symlink, is malformed. - Content comes back inline as base64, up to 5 MiB. A larger file or zip is a resolution error that names the streaming route to use instead,
GET /v1/files/orGET /v1/dirs/(HTTP API). Files are written over HTTP only (PUT /v1/files/). file.getreads regular files only; a directory, FIFO or device is refused without blocking.directory.getzips regular files and directories, and skips and counts symlinks and special files.
ref or literal
Section titled “ref or literal”input.type and dom.fill each take exactly one of:
ref: the name of a value in the loaded scenario’sprovides:map. The runtime resolves it inside the session and never echoes it back.- a literal (
textforinput.type,valuefordom.fill) that your agent composes.
Giving both, or neither, is a malformed call. A ref with no scenario loaded, or a ref the scenario does not provide, is a resolution error. A scenario is loaded with KASM_RUNTIME_SCENARIO_B64; a driven session usually has none.
- HTTP API: the same methods as plain HTTP calls, plus file transfer and the observe routes.
- Using it with your own agent: how an outside agent and the runtime divide the work.
- Drive a session from Claude Code: these methods in use.