@struktoai/mirage-edge runs Mirage on an edge runtime: a host with web Request/Response, no Node and no threads. A workspace runs in the runtime’s own isolate: the shell, the commands built on Rust, and python3 on Monty, all in one thread.
The runtime needs:
- Node’s
buffer,crypto,path,processandutilmodules. - A bundler that loads a
.wasmimport as a compiledWebAssembly.Module. Mirage’s Rust module and Monty both load this way.
Install
wrangler.toml
Run a workspace
src/worker.ts
python3 runs on Monty in the isolate’s own thread, where no timer can interrupt it, so Monty’s own clock stops a run: at the line’s time limit, which ends the line with exit 124, or after 30 seconds with TimeoutError if that comes first. A loop that never ends leaves the isolate free for the next line.
For anything else from core, import its subpaths (@struktoai/mirage-core/vfs/registry), not its package root: the root also imports optional packages, such as Pyodide, that an edge bundle cannot resolve.
Serve the server API
createApp answers the HTTP routes, MCP and RPC as the server does, over the workspaces the isolate holds:
src/worker.ts
no_handle_cross_request_promise_resolution above lets it.
It checks each request the way the server does, from the same MIRAGE_AUTH_MODE, MIRAGE_AUTH_TOKEN and MIRAGE_JWT_* variables. Without a token or a JWT issuer it serves nothing, since an edge app’s URL is public.
wrangler.toml
Limits
- An edge isolate has little memory and no disk; a Cloudflare Worker has 128 MB. Set
max_memoryon each workspace so a large write fails withDisk quota exceededbefore the isolate runs out. - Workspaces live in the isolate’s memory. A request routed to another isolate does not see them, and they are gone when the isolate is evicted.
store.typemust beram. - A config’s mounts come from core’s VFS table:
ram,github,gdrive,gdocs,gsheets,gslides,gcal,gmail,onedrive,sharepoint,box,airtable,linear,trello,langfuse,wandb,mem0,qdrantanddify.qdrantneeds@qdrant/js-client-restinstalled; without it the bundle still builds and the mount refuses.chromaloads its package by a name only known at run time, which an edge runtime cannot do. - Network rules judge each request by host name: the isolate never sees the address a name reaches, so a
denied_domainsentry naming an address or a range is refused, and jwt mode’s block on cloud metadata addresses covers only a request made to the address itself. - SSH, FUSE, policy and script files read by path, and runtimes or CLIs loaded by a
source:Classreference are the Node server’s alone.