Skip to main content
The in-app API is what every other interface is built on: HTTP, MCP, RPC, SSH and the CLI all end in the calls on this page. Use it directly when your agent runs in the same process as the workspace.

Workspace and Session

A Session is one session’s handle: shell runs a line as it, glob matches as it, and vfs is the file API run as it, so every call answers under the session’s profile, with its working directory, environment, mount modes and hides.
ws.session(id) creates the session when the id is new and adopts it when it exists. Pass { profile } to create it under one of the workspace’s profiles, or { mounts } to narrow its mount modes. A profile, mounts or permissions for an existing session throw, since a profile is set once, when the session is created. ws.shell(line, { sessionId }) and ws.glob(pattern, sessionId) are the same calls without the handle; without a session id they act as the workspace’s default session.

session.shell

It answers a result with exitCode, stdoutText and stderrText (stdout and stderr are the bytes). A non-zero exit is a result, not an exception.

Cancel a line

Abort the signal. The line stops at its next await, $? goes back to what it was before the line ran, and the call throws a DOMException named AbortError:
A long synchronous step, such as one large read, finishes before the abort lands. A command that runs past its limit is not a cancel: it exits 124.

session.vfs

The file API, run as the session. Paths are absolute workspace paths, and bytes are Uint8Array. A failure throws an Error whose code is the POSIX name, as Node’s fs does: ENOENT for a missing path, EROFS or EACCES for a refused one.

The agent tool table

MirageToolOperations is the seven agent tools (shell, read, write, edit, ls, grep, glob) as a class, answered for one session. MCP, RPC’s tools/call, the HTTP tool routes and the CLI’s tool verbs all call it, so an agent loop of your own gets the same answers:
Each tool is also a method: await tools.read('/data/report.csv', 0, 20), await tools.grep('todo', '/src', { ignoreCase: true }). call takes the arguments as the schema reads them, is what every interface uses, and throws for a name no tool has. readMedia(path) answers an image or a PDF as media instead of numbered text, for adapters that hand media to the model. @struktoai/mirage-agents/tool_descriptions exports each tool’s description and JSON schema (READ_DESCRIPTION, READ_INPUT, …) to hand your model, and the agent adapters wrap the table for each framework.

Embed the MCP server

The MCP server the Mirage server runs is a factory you can call yourself, over any MCP transport, without the Mirage server:
It returns the SDK’s McpServer. To serve it over streamable HTTP from your own route, hand the factory to the SDK’s createMcpHandler(() => createMirageMcpServer(ws, { operations })), sharing one operations across requests so stale-write stamps carry from one request to the next, which is what the Mirage server does.

Embed the RPC server

MirageRpcServer serves one session over JSON-RPC, with the same methods the Mirage server answers. handle answers one message, for a route of your own; serve answers a stream of lines until it ends, running each request on its own so $/cancelRequest reaches a running one:
In-app, shell runs the line directly on the session; the Mirage server runs it as a job instead.

Reach a server from code

When the workspace lives in a server, fetch reaches it. The token is in ~/.mirage/auth_token in the default local mode:
POST /rpc carries the whole Session API in one route; the HTTP page lists the rest, and the RPC page shows a mirage rpc client over stdio.