Skip to main content
The Mirage server is a FastAPI app. It holds workspaces and serves them over the HTTP routes, MCP and RPC, and over SSH, on its own port when ssh_port is set and through its HTTP port either way. The TypeScript server speaks the same protocol, so a client of one works against the other.

Install

The ssh extra adds asyncssh, needed only for the SSH server.

Run it

build_app returns the app. Run it with any ASGI server; it serves until you stop it.

Started by the CLI

The CLI runs the same app as a daemon, mirage.server.daemon:app, on 127.0.0.1:8765 in local auth mode, logging to ~/.mirage/daemon.log. That entry adds the two daemon behaviors: it writes $MIRAGE_HOME/daemon.pid for mirage daemon stop and kill, and exits 30 seconds (MIRAGE_IDLE_GRACE_SECONDS) after its last workspace is deleted. Its settings are on the CLI page.

Beside your own event loop

WorkspaceRunner pins a workspace to a thread and event loop of its own. A slow line then never stalls your app’s loop, and workspaces in one process never hold each other up. The Mirage server hosts every workspace this way.
call runs a coroutine on the workspace’s loop and is safe from any other loop; cancelling the caller cancels the coroutine. stop closes the workspace (delete=True also deletes its state), then stops the loop and refuses new calls.

MCP and RPC on their own

The MCP and RPC servers are classes you can run over a transport of your own, without the Mirage server. Both serve one session of a workspace.
MirageMcpServer(workspace, stale_write_protection=True, name="mirage", version=..., session_id=None, operations=None, all_calls=False). Its server is the MCP SDK’s low-level Server. all_calls=True adds the VFS calls and explain.
MirageRpcServer(workspace, session_id=None, operations=None, name="mirage", version=...). handle(message) answers one message, and None for a notification. serve(read_line, write_line) answers newline-delimited messages until read_line returns "".

What is particular to this server

The protocol is the same on both servers. These are the differences in how this one serves it:
  • SSH output streams. A line’s output over SSH is sent as the line produces it. The TypeScript server sends it when the line finishes.
  • Legacy scp -O. The SCP protocol is served, as well as SFTP.
  • authorized_keys options. asyncssh enforces OpenSSH’s options (from=, command=, …), and command= forces the line that runs. mirage-profile binds the key to a profile.
  • Terminal line limit. 1024 characters.
  • A thread per workspace. Each workspace runs on its own thread and event loop through a WorkspaceRunner, so a busy workspace does not hold up another or the HTTP server.

Code map