> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirage.strukto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Server

> The Mirage server in TypeScript, a Fastify app that holds workspaces and serves HTTP, MCP, RPC and SSH.

The Mirage server is a Fastify app from `@struktoai/mirage-server`. It holds workspaces and serves them over the [HTTP](/home/access/http) routes, [MCP](/home/access/mcp) and [RPC](/home/access/rpc), and over [SSH](/home/access/ssh), on its own port when `ssh_port` is set and through its HTTP port either way. The Python server speaks the same protocol, so a client of one works against the other.

## Install

<CodeGroup>
  ```bash npm theme={null}
  npm install @struktoai/mirage-server
  ```

  ```bash with SSH theme={null}
  npm install @struktoai/mirage-server ssh2
  ```
</CodeGroup>

The SSH server runs on [ssh2](https://github.com/mscdex/ssh2), installed beside the server, needed only for SSH.

## Run it

`buildApp` returns the Fastify instance; it serves until you stop it.

```ts theme={null}
import { buildApp } from '@struktoai/mirage-server'

const app = buildApp()
await app.listen({ host: '127.0.0.1', port: 8765 })
```

| Option | Default | Meaning |
| - | - | - |
| `authConfig` | from `MIRAGE_AUTH_MODE` | Token or JWT [auth](/home/access/http#auth). |
| `allowedHosts` | `MIRAGE_ALLOWED_HOSTS`, else loopback | `Host` names the app answers. `['*']` turns the check off, safe only behind a trusted proxy. |
| `sshConfig` | from the `ssh_*` settings | The SSH server, opened when the app is ready; off unless a port is set, and `null` keeps it off. |
| `snapshotStore` | none | An `S3Config`: the store a snapshot request may name a key in. Without one, a snapshot only goes back to the caller; the server never writes one to its own disk. |
| `stateRoot` | under `$MIRAGE_HOME` | Where live state is kept. |
| `onIdleExit` | a no-op | Called when the last workspace has been gone `idleGraceSeconds` (30), or on `POST /v1/shutdown`. |

## Started by the CLI

`@struktoai/mirage-cli` runs the same app as a daemon, `mirage-daemon`, 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. It listens on `MIRAGE_DAEMON_PORT`, the `port` setting, or `8765`. Its settings are on the [CLI page](/home/access/cli#config).

## MCP and RPC on their own

The [MCP](/home/access/mcp) and [RPC](/home/access/rpc) servers can run over a transport of your own, without the Mirage server. Both serve one session of a [workspace](/typescript/access/in-app).

```ts theme={null}
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio'
import { createMirageMcpServer } from '@struktoai/mirage-server/mcp'

const server = createMirageMcpServer(ws, { sessionId: 'agent' })
await server.connect(new StdioServerTransport())
```

`createMirageMcpServer(ws, { sessionId?, operations?, name?, version?, staleWriteProtection?, allCalls? })` returns the MCP SDK's `McpServer`. `allCalls: true` adds the [VFS calls and explain](/home/access/mcp#vfs-calls-and-explain).

```ts theme={null}
import { MirageRpcServer } from '@struktoai/mirage-server/rpc'

const server = new MirageRpcServer(ws, { sessionId: 'agent' })
const answer = await server.handle({
  jsonrpc: '2.0',
  id: 1,
  method: 'glob',
  params: { pattern: '/*' },
})
```

`new MirageRpcServer(ws, { sessionId?, operations?, name?, version? })`. `handle(message)` answers one message, and `null` for a notification. `serve(lines, write)` answers each line of an async iterable until it ends.

## 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 is sent whole.** A line's output over SSH is sent when the line finishes, as HTTP sends it. The Python server streams it.
* **No legacy `scp -O`.** Modern `scp` uses SFTP, which is served; the old SCP protocol is not.
* **`authorized_keys` options.** Only `mirage-profile` is read, which binds the key to a [profile](/home/access/ssh#bind-a-key-to-a-profile). A key line carrying any other option (`from=`, `command=`, ...) is skipped with a warning, rather than accepted as if it had none.
* **Terminal line limit.** 1024 bytes.
* **One event loop.** Every workspace shares Node's loop. Shell evaluation yields between steps, but a long synchronous step in a JavaScript callback or a CPU-heavy runtime holds every workspace until it returns, so run such work in a worker.

## Code map

| Path | What |
| - | - |
| [`packages/server/src/app.ts`](https://github.com/strukto-ai/mirage/blob/main/typescript/packages/server/src/app.ts) | `buildApp`: routers, MCP and RPC endpoints, the SSH server. |
| [`packages/server/src/bin/daemon.ts`](https://github.com/strukto-ai/mirage/blob/main/typescript/packages/server/src/bin/daemon.ts) | `mirage-daemon`, the daemon entry the CLI starts. |
| [`packages/server/src/routers/`](https://github.com/strukto-ai/mirage/tree/main/typescript/packages/server/src/routers) | The HTTP routes: workspaces, sessions, shell, tools, jobs, asks. |
| [`packages/server/src/mcp/`](https://github.com/strukto-ai/mirage/tree/main/typescript/packages/server/src/mcp) | `createMirageMcpServer`, the `/mcp` endpoint, and the stdio relay `mirage mcp` runs. |
| [`packages/server/src/rpc/`](https://github.com/strukto-ai/mirage/tree/main/typescript/packages/server/src/rpc) | `MirageRpcServer`, the `/rpc` endpoint, and the stdio relay `mirage rpc` runs. |
| [`packages/server/src/ssh/`](https://github.com/strukto-ai/mirage/tree/main/typescript/packages/server/src/ssh) | The SSH server: shell, exec and SFTP. |
| [`packages/core/src/workspace/tools/`](https://github.com/strukto-ai/mirage/tree/main/typescript/packages/core/src/workspace/tools) | The agent tool table behind `session.tools`, which every interface calls. |
| [`packages/cli/src/`](https://github.com/strukto-ai/mirage/tree/main/typescript/packages/cli/src) | The `mirage` CLI, one module per verb. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.