Skip to content
Draft, pre-release documentation

When KASM_RUNTIME_SESSION_TOKEN is set, kasm-session-runtime mcp serves HTTP on KASM_SESSION_RUNTIME_PORT (default 9434). The listener carries MCP, the same methods as plain HTTP calls, file transfer, an optional pass-through to the browser’s DevTools port, and the observe and inbox routes a sidebar reads. This page lists every route by group, with the credential each takes.

No route needs a model in the runtime except the three method calls that ask the vision model, screen.judge, screen.ground and screen.ask (see MCP methods).

A running server describes itself at GET /v1/openapi.json, with no credential. It is an OpenAPI 3.1 document generated from the routes as mounted in that process: every method’s parameter schema, every request and response body, and each route’s credential as configured. Use it to generate a client, or to check what a particular session has switched on. The tables below summarise it.

Through Kasm, the base is https://<host>/desktop/<kasm_id>/mcp/, where mcp is the name of the Kasm port-map entry for port 9434. Every path below is relative to that base.

Credential Set by Sent as
Session token KASM_RUNTIME_SESSION_TOKEN the X-Kasm-Runtime-Session-Token header; ?token= only where a route accepts it
Messaging token KASM_RUNTIME_INBOX_TOKEN the same header or ?token=; the value decides which token it is

The session token is the credential of whoever drives or consumes the session. The messaging token is the narrower one a sidebar holds for people’s messages. Neither goes in Authorization, because Kasm’s port-map proxy overwrites that header before forwarding. A missing or wrong credential gets 401.

Method Path Credential What it does
POST /mcp session token MCP Streamable HTTP: JSON-RPC requests, answered as JSON or an event stream
GET /mcp session token the server-to-client stream, for protocol versions before 2026-07-28
DELETE /mcp session token ends a session, for protocol versions before 2026-07-28

The Mcp-Protocol-Version header picks the protocol. From 2026-07-28 each POST stands alone, with no initialize and no session; GET and DELETE then return 405.

Method Path Credential What it does
POST /v1/call/<method> session token runs one of the 28 methods; the body is its parameters as a JSON object, and an empty body is {}

A call returns 200 {"result": ...} or {"error": {"class", "message"}}:

Status Error class Meaning
400 malformed the body is not one JSON object, or the parameters fail the method’s schema or checks
404 malformed no such method; nothing ran and no step is recorded
413 malformed the body is over 8 MiB
422 resolution a capability is unavailable, something was not found, or a wait timed out
500 environment, internal, error the runtime failed
503 shutting_down, cancelled the call never ran

A call that runs records one row in report.json’s steps[], the same row the method records over MCP.

Terminal window
curl -s -X POST -H "X-Kasm-Runtime-Session-Token: $TOKEN" \
-d '{"chord": "ctrl+s"}' \
"https://<host>/desktop/<kasm_id>/mcp/v1/call/input.key"

{root} is home or tmp. Paths may not leave the root, including through a symlink.

Method Path Credential What it does
GET /v1/files/{root}/{path} session token streams a regular file; the X-Kasm-Runtime-Sha256 trailer carries its SHA-256
PUT /v1/files/{root}/{path} session token writes a file, streamed; ?overwrite=true to replace, ?mode=0755 to set the mode
GET /v1/dirs/{root}/{path} session token streams a directory as a zip of its regular files and directories
PUT /v1/dirs/{root}/{path} session token extracts an uploaded zip into a directory; ?overwrite=true to replace
  • A PUT answers 201 when nothing was there and 200 when it replaced a file. Without overwrite, something already at the path gets 409 and nothing is replaced.
  • Uploads are capped by KASM_RUNTIME_UPLOAD_MAX_BYTES and an archive’s extracted size by KASM_RUNTIME_EXTRACT_MAX_BYTES, both 1 GiB by default; over the cap is 413. An archive is checked in full before anything is extracted, and may hold at most 10,000 entries.
  • At most four transfers run at once; the next gets 503 busy and should retry. A stream that makes no progress for 60 seconds is cut off.
  • A finished transfer appears as a transfer event on /events, without its content.

Mounted only when KASM_ENABLE_CDP=true as well as the session token.

Method Path Credential What it does
GET /cdp/{path} session token Chrome’s DevTools HTTP endpoints and WebSocket, proxied
PUT /cdp/{path} session token the same, for DevTools endpoints that take PUT

A generic Chrome DevTools Protocol client, such as Playwright or Puppeteer, then has the whole of the session’s browser, including every tab and arbitrary JavaScript. The discovery responses’ WebSocket URLs are rewritten to point back through this route. Chrome must be running with --remote-debugging-port and --user-data-dir; otherwise every request gets 502. Through Kasm this needs a second port-map entry named cdp on the same port, so the address is https://<host>/desktop/<kasm_id>/cdp/cdp/json/version.

These are what a sidebar reads to follow a run. They are also served by kasm-session-runtime run when KASM_RUNTIME_OBSERVE=1.

Method Path Credential What it does
GET /events read rule server-sent events, one per line of the run’s trace.jsonl
GET /artifacts/report.json read rule the run’s report as last written
GET /artifacts/trace.jsonl read rule every event /events streams, one per line
GET /artifacts/{path} read rule any other file in the run’s output directory, such as screenshots/NN-label.jpg

Under the read rule, reads need no credential by default and rely on Kasm’s session cookie, which the port-map proxy checks before forwarding. With KASM_RUNTIME_OBSERVE_TOKEN_REQUIRED=true they need the session or the messaging token, in the header or as ?token= (an EventSource or <img> cannot set a header). KASM_RUNTIME_OBSERVE_INPUT=true turns the gate on, because the trace then holds keystrokes. A gated read with neither token configured is refused with 503. The OpenAPI document’s x-kasm-runtime-observe-gate field says which rule a running server uses.

If you expose the port without Kasm’s proxy in front, the open reads expose screenshots and tool results; turn the gate on or put your own authentication in front.

Event types and file handling are on Sidebar protocol.

These routes carry the channel between people in the session and the run. They are mounted when KASM_RUNTIME_INBOX_TOKEN or the session token is set; otherwise they return 404. Reads follow the read rule above.

Method Path Credential What it does
POST /messages messaging or session token posts a message to the run
GET /messages read rule lists messages since a revision (?since=) or by state (?state=)
GET /messages/{id} read rule one message
GET /runs/{run}/messages/{key} messaging or session token looks up a message by the idempotency key the caller posted it under
POST /attachments messaging or session token uploads an attachment to reference from a message
GET /attachments/{id} read rule one attachment; ?inline=1 for images
POST /requests session token only asks the person a typed question
GET /requests read rule lists requests, optionally by ?state=
GET /requests/{id} read rule one request
POST /requests/{id}/cancel session token only closes a request without a reply
POST /actions messaging or session token; ack needs the session token a control action: stop, finish_handoff or ack
GET /inbox read rule the run id, epoch, revision, counts by state and open requests

The sender recorded on a message comes from the credential: operator for the messaging token, orchestrator for the session token. JSON bodies on these routes are capped at 1 MiB; attachments have their own cap, evidence.inbox_attachment_bytes in the operator file. The request and message shapes, idempotency keys and states are on Sidebar protocol.