@cogineai/mafs-server
v0.1.0-alpha.0
Published
mafs daemon server for agent workspace filesystems
Maintainers
Readme
@cogineai/mafs-server
mafs-daemon — a Fastify-based HTTP server that exposes MAFS Workspaces over a stable JSON API, plus the building blocks to embed that API into your own Fastify app.
This is the daemon backing the mafs CLI. It's also how non-TypeScript clients talk to MAFS: the Python bridge uses these endpoints, browser apps proxy through them when they need Node-only resources, and the CogineX control plane uses the daemon as its data-plane HTTP boundary.
Install
# As a global CLI:
npm install -g @cogineai/mafs-server
# As a library (embed the routes into your own Fastify app):
npm install @cogineai/mafs-serverRequires Node.js ≥ 20.
Run the daemon
mafs-daemon
# starts on 127.0.0.1:8765 by default
# Or via npx without a global install:
npx @cogineai/mafs-serverConfiguration is via environment variables:
| Env | Default | Description |
| ------------------------- | ---------- | --------------------------------------------------------------------------------------------------- |
| MAFS_DAEMON_PORT | 8765 | Listen port. |
| MAFS_ALLOWED_HOSTS | loopback | Comma-separated Host-header allow-list (DNS rebinding protection). |
| MAFS_PERSIST_DIR | disabled | When set, the daemon snapshots / restores workspace state to this directory across restarts. |
| MAFS_IDLE_GRACE_SECONDS | 30 | Seconds without a workspace before the daemon self-exits; also the grace window after the last one. |
The daemon always binds to 127.0.0.1; for non-loopback exposure, run behind a reverse proxy and set MAFS_ALLOWED_HOSTS accordingly.
The daemon is loopback-only by default and rejects any HTTP request whose Host header is not in MAFS_ALLOWED_HOSTS. This prevents DNS rebinding attacks when developers run the daemon alongside a browser.
HTTP API
All routes are mounted under the /v1 prefix.
| Path | Methods | Description |
| ------------------------------------------ | --------------- | -------------------------------------------------------------------------- |
| /v1/health | GET | Liveness probe. |
| /v1/shutdown | POST | Trigger graceful shutdown. |
| /v1/workspaces | POST | Create a workspace from a CreateWorkspaceRequest ({ id?, config }). |
| /v1/workspaces | GET | List workspaces (brief shape). |
| /v1/workspaces/{id} | GET | Inspect a workspace; pass ?verbose=true for cache / history internals. |
| /v1/workspaces/{id} | DELETE | Stop and destroy a workspace. |
| /v1/workspaces/{id}/snapshot | GET | Stream a tar snapshot of the workspace as the response body. |
| /v1/workspaces/load | POST | Load a workspace from a multipart tar (tar + optional id, override). |
| /v1/workspaces/{id}/clone | POST | Clone a workspace with optional override. |
| /v1/workspaces/{id}/refresh | POST | Clear file / index cache for a workspace path ({ path? }). |
| /v1/workspaces/{id}/execute | POST | Run a shell command (sync; pass ?background=true to return a jobId). |
| /v1/workspaces/{id}/sessions | POST, GET | Create / list sessions. |
| /v1/workspaces/{id}/sessions/{sessionId} | DELETE | End a session. |
| /v1/jobs | GET | List jobs (?workspaceId= filter). |
| /v1/jobs/{id} | GET, DELETE | Inspect or cancel a job spawned by execute. |
| /v1/jobs/{id}/wait | POST | Block until a job completes (optional { timeoutS }). |
All requests and responses are JSON; the canonical shapes are in packages/server/src/schemas.ts.
Use programmatically
buildApp returns a fully-built Fastify instance. Call it from your own bootstrap when you want full control over the listen address, logging, persistence directory, or DNS-rebinding allow-list:
import { buildApp } from '@cogineai/mafs-server'
const app = buildApp({
persistDir: '/var/lib/myapp/mafs',
idleGraceSeconds: 60,
allowedHosts: ['mafs.internal'], // or ['*'] behind a trusted reverse proxy
})
await app.restorePromise // wait for any persisted workspaces to restore
await app.listen({ port: 8765, host: '127.0.0.1' })The package also exports config helpers — loadWorkspaceConfig, interpolateEnv, configToWorkspaceArgs, and types WorkspaceConfigRaw, WorkspaceArgs, MountBlock — that the @cogineai/mafs-cli mafs workspace create command uses to load a YAML/JSON workspace descriptor into the config field of the create request. They are useful if you want to construct create-request bodies in your own clients.
There is no public router-by-router embed API: the daemon is shipped as one cohesive Fastify instance and is intended to run standalone (process or sidecar).
Quick start — create, execute, snapshot
# The daemon auto-spawns on the first command that needs it.
mafs workspace create ws.yaml --id demo
mafs execute --workspace demo --command 'echo hello > /data/hello.txt && cat /data/hello.txt'
mafs workspace snapshot demo demo.tarOr hit the HTTP API directly:
# Health.
curl -fsSL http://127.0.0.1:8765/v1/health
# Create. The body matches CreateWorkspaceRequest = { id?, config }.
curl -fsSL http://127.0.0.1:8765/v1/workspaces \
-H 'Content-Type: application/json' \
--data '{"id":"demo","config":{"mounts":{"/data":{"type":"ram"}},"mode":"write"}}'
# Execute (synchronous; pass ?background=true to get a jobId back instead).
curl -fsSL http://127.0.0.1:8765/v1/workspaces/demo/execute \
-H 'Content-Type: application/json' \
--data '{"command":"echo hello > /data/hello.txt && cat /data/hello.txt"}'Companion packages
@cogineai/mafs-cli—coginex+mafsbinaries (themafsCLI talks to this daemon).@cogineai/mafs-core— runtime-agnostic primitives the daemon serves over HTTP.@cogineai/mafs-node— Node resources used by the daemon to back workspaces.@cogineai/mafs-browser— browser bundle that can talk to this daemon when it needs Node-only resources.@cogineai/mafs-agents— adapters for agent frameworks.
License & attribution
Apache-2.0. MAFS is a fork of Mirage; see the project-level NOTICE for attribution and the relationship to upstream.
