HTTP API
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).
The OpenAPI document
Section titled “The OpenAPI document”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.
Base address and credentials
Section titled “Base address and credentials”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 calls
Section titled “Method calls”| 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.
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"File transfer
Section titled “File transfer”{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
PUTanswers 201 when nothing was there and 200 when it replaced a file. Withoutoverwrite, something already at the path gets 409 and nothing is replaced. - Uploads are capped by
KASM_RUNTIME_UPLOAD_MAX_BYTESand an archive’s extracted size byKASM_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
busyand should retry. A stream that makes no progress for 60 seconds is cut off. - A finished transfer appears as a
transferevent on/events, without its content.
CDP passthrough
Section titled “CDP passthrough”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.
Observe routes
Section titled “Observe routes”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.
Inbox routes
Section titled “Inbox routes”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.
- MCP methods: what each
/v1/call/method does and how it fails. - Sidebar protocol: the events and inbox wire in detail.
- What the process can reach: how these credentials fit the runtime’s security model.