Asynchronous execution & output¶
Recipes for submitting code, polling results, streaming output, cancelling runs, and using the synchronous shortcut — all through MCP tools or the REST API.
Submit and poll via MCP tools¶
In stateful mode, run_js returns an execution_id. Poll with get_execution until the status leaves running.
// 1. Submit
{ "tool": "run_js", "arguments": { "code": "console.log('hello');" } }
// Response: { "execution_id": "01J9W…" }
// 2. Poll
{ "tool": "get_execution", "arguments": { "execution_id": "01J9W…" } }
// Response: { "execution_id": "01J9W…", "status": "completed", "result": null,
// "heap": "sha256:…", "error": null,
// "started_at": "…", "completed_at": "…" }
Poll until status is one of completed, failed, cancelled, or timed_out.
Read console output by line¶
get_execution_output returns paginated console.log output. Omitting pagination parameters returns lines 1–100 (default line_offset = 1, line_limit = 100).
{
"tool": "get_execution_output",
"arguments": { "execution_id": "01J9W…" }
}
To read the next page, pass the next_line_offset value from the previous response as line_offset:
{
"tool": "get_execution_output",
"arguments": {
"execution_id": "01J9W…",
"line_offset": 101,
"line_limit": 100
}
}
Repeat while has_more is true.
Read console output by byte¶
Byte-based mode is useful when output contains multi-line structured text or when you need exact byte positions. Providing byte_offset activates byte mode (overrides line-based parameters). The default byte_limit is 4096 bytes.
{
"tool": "get_execution_output",
"arguments": {
"execution_id": "01J9W…",
"byte_offset": 0,
"byte_limit": 8192
}
}
Use next_byte_offset from the response as byte_offset for the next page.
Read output while execution is still running¶
Both get_execution_output and GET /api/executions/{id}/output work while the execution is running. The status field in the response reflects the execution state at the time of the query, and total_lines / total_bytes reflect what has been written so far. Call again with next_line_offset or next_byte_offset to pick up new output.
Cancel a running execution¶
Use cancel_execution to terminate the V8 isolate immediately. Cancellation only succeeds when the execution is running; calling it on an already-finished execution returns an error.
{ "tool": "cancel_execution", "arguments": { "execution_id": "01J9W…" } }
// Success: { "ok": true }
// Already finished: { "ok": false, "error": "Execution '01J9W…' is not running (status: completed)" }
Via REST:
curl -s -X POST http://localhost:8080/api/executions/$EID/cancel
200 { "ok": true } on success; 400 { "ok": false, "error": "…" } when the execution is not in running state.
List all executions¶
list_executions returns a summary of every execution the server currently tracks (both in-flight and recently finished):
{ "tool": "list_executions", "arguments": {} }
// Response: { "executions": [ { "execution_id": "…", "status": "…",
// "started_at": "…", "completed_at": "…" }, … ] }
Via REST:
curl -s http://localhost:8080/api/executions
Use the stateless synchronous shortcut¶
When the server is running in stateless mode (--stateless), run_js is the only available tool and it blocks until the execution completes (polling internally every 50 ms, up to 300 seconds). It returns the full console output directly — no separate get_execution_output call is needed.
{ "tool": "run_js", "arguments": { "code": "console.log(1 + 1);" } }
// Success: { "output": "2" }
// Failure: { "output": "…", "error": "ReferenceError: x is not defined" }
The stateless run_js accepts only code, heap_memory_max_mb, and execution_timeout_secs. The heap, tags, and session parameters are not available in stateless mode.
Pass execution options¶
Both MCP run_js and REST POST /api/exec accept optional per-execution limits:
| Parameter | Type | Effect |
|---|---|---|
heap_memory_max_mb |
integer | Override the server's heap memory cap for this execution |
execution_timeout_secs |
integer (1–300) | Override the server's timeout for this execution |
curl -s -X POST http://localhost:8080/api/exec \
-H 'Content-Type: application/json' \
-d '{"code":"/* heavy work */","heap_memory_max_mb":32,"execution_timeout_secs":60}'