Gateway CLI Reference
The Freesail Gateway is the central bridge between AI agents and browser-based frontends. It is started via the freesail CLI.
Starting the Gateway
Section titled “Starting the Gateway”freesail run gateway [options]You can also invoke the gateway binary directly if installed:
freesail-gateway [options]CLI Options
Section titled “CLI Options”| Option | Default | Description |
|---|---|---|
--config <file> | freesail-gateway.config.json | Path to JSON config file in CWD |
--http-port <port> | 3001 | Port for the A2UI HTTP/SSE server |
--http-host <host> | 0.0.0.0 | Bind address for the A2UI server |
--mcp-mode <mode> | http | MCP transport: http (standalone) or stdio (child process) |
--mcp-port <port> | 3000 | Port for MCP Streamable HTTP server (http mode only) |
--mcp-host <host> | 127.0.0.1 | Bind address for MCP server (http mode only) |
--session-timeout <s> | 1800 | Session idle timeout in seconds |
--reconnect-grace-period <s> | 180 | Session resumption window in seconds |
--log-file <file> | — | Write logs to file (in addition to console) |
--log-level <level> | info | Minimum log level: fatal | error | warn | info | debug |
--log-filter <f> | — | Per-subsystem level override, e.g. express:debug. Repeatable. |
--help | — | Show help |
CLI flags always take precedence over config file values.
Examples
Section titled “Examples”# Default — HTTP MCP on port 3000, A2UI on port 3001freesail run gateway
# Custom portsfreesail run gateway --http-port 8080 --mcp-port 4000
# Stdio MCP mode (agent spawns gateway as a child process)freesail run gateway --mcp-mode stdio
# With a config filefreesail run gateway --config /etc/freesail/gateway.json
# Suppress MCP noise, verbose session eventsfreesail run gateway --log-level warn --log-filter session:debug
# Log to file, suppress MCP noisefreesail run gateway --log-file gateway.log --log-level info --log-filter mcp:warn
# Verbose agent-surface events onlyfreesail run gateway --log-filter session.agent-surface:debugConfig File
Section titled “Config File”All settings can be provided via a JSON config file. By default the gateway looks for freesail-gateway.config.json in the current working directory. Override the path with --config.
A sample config is included in the package:
cp node_modules/@freesail/gateway/freesail-gateway.config.sample.json freesail-gateway.config.jsonFull Config File Reference
Section titled “Full Config File Reference”{ "httpPort": 3001, "httpHost": "0.0.0.0", "mcpMode": "http", "mcpPort": 3000, "mcpHost": "127.0.0.1", "webhookUrl": "http://localhost:3002/action", "sessionTimeout": 3600, "reconnectGracePeriod": 180, "catalogLogDir": "/var/log/freesail/catalogs", "bodyLimit": "5mb", "log": { "level": "info", "file": "/var/log/freesail/gateway.log", "filters": { "express": "info", "mcp": "warn", "session": "info", "session.agent-surface": "debug", "session.client-surface": "warn" } }}All fields are optional; omit any you don’t need and the defaults will apply.
Note:
sessionTimeoutandreconnectGracePeriodare specified in seconds in the config file, not milliseconds.
Network Interfaces
Section titled “Network Interfaces”The gateway exposes two independent network interfaces:
| Interface | Default Port | Protocol | Purpose |
|---|---|---|---|
| Agent-facing | 3000 | MCP Streamable HTTP | Exposes tools, resources, and prompts to AI agents |
| UI-facing | 3001 | HTTP SSE + POST | Streams A2UI updates to frontends; receives user actions |
By default the MCP server binds to 127.0.0.1 (localhost only) for network isolation. The A2UI server binds to 0.0.0.0 so browsers can connect.
Session Management
Section titled “Session Management”Session Timeout
Section titled “Session Timeout”Idle sessions are removed after 30 minutes by default. Override in the config file:
{ "sessionTimeout": 3600 }Reconnect Grace Period
Section titled “Reconnect Grace Period”When a browser tab closes (or page refreshes), the gateway suspends the session for a grace period rather than removing it immediately. If the client reconnects within this window, the session is resumed seamlessly — including all surface state. The default is 180 seconds.
{ "reconnectGracePeriod": 300 }The client stores the session ID in sessionStorage (tab-scoped) and sends it as the X-Freesail-Session header on reconnect. The gateway matches this to the suspended session and resumes it. If two browser tabs share the same sessionStorage value (e.g. after duplicating a tab), the gateway detects the collision and creates a fresh session for the duplicate.
Security
Section titled “Security”CSRF Protection
Section titled “CSRF Protection”The gateway sets an HttpOnly; SameSite=Strict cookie (freesail-gateway-token) on every SSE connection. All write endpoints (/message, /register-surface, /register-catalogs) validate the presence of this cookie. SameSite=Strict prevents cross-site requests from including it, blocking CSRF attacks.
Session Identity
Section titled “Session Identity”Session identity is carried via the X-Freesail-Session header (set by the transport from sessionStorage), not the CSRF cookie. This ensures each browser tab maintains its own independent session.
User Context Propagation
Section titled “User Context Propagation”When deployed behind a reverse proxy such as nginx, the gateway reads the X-User-Context header on every SSE connection and stores the parsed JSON as userContext on the session. Agents receive this via list_sessions.
location /sse { proxy_set_header X-User-Context '{"userId":"$jwt_sub","orgId":"$jwt_org_id"}'; proxy_pass http://127.0.0.1:3001;}The header must be a valid JSON object. The gateway trusts it as-is — it must only be set by a trusted reverse proxy, never by the browser.
Logging
Section titled “Logging”Log levels
Section titled “Log levels”fatal | error | warn | info (default) | debug
Log subsystem filters
Section titled “Log subsystem filters”Use --log-filter <subsystem>:<level> (repeatable) or log.filters in the config file to override the log level for individual subsystems:
| Subsystem | Covers |
|---|---|
express | SSE connections, incoming actions, catalog registration |
mcp | Agent MCP tool calls, session handshake |
session | Surface creates/updates, data-model writes, stale-session cleanup |
session.agent-surface | Downstream messages sent to agent-created surfaces |
session.client-surface | Downstream messages sent to client-managed surfaces (__ prefix) |
Dot-notation maps to nested log categories (e.g. session.agent-surface → ['freesail', 'session', 'agent-surface']).
MCP Resources (Push Notifications)
Section titled “MCP Resources (Push Notifications)”The gateway exposes MCP resources that agents subscribe to for push-based delivery — no polling required.
| URI | Description |
|---|---|
mcp://freesail.dev/sessions | List of active sessions. Fires ResourceUpdated on every connect/disconnect. |
mcp://freesail.dev/sessions/{sessionId} | Pending action queue for a specific session. Fires ResourceUpdated on every new action. Reading the resource drains the queue. |
Agent runtimes using @freesail/agent-runtime subscribe to these automatically. See the Agent Runtime reference for details.
MCP Tools
Section titled “MCP Tools”The gateway exposes the following MCP tools to connected agents:
| Tool | Description |
|---|---|
create_surface | Initialize a new UI surface for a client session |
update_components | Update the component tree of a surface |
update_data_model | Update the data model without changing component structure |
get_data_model | Retrieve the current client-side data model for a surface on demand |
get_component_tree | Retrieve the current component tree for a surface from the client |
delete_surface | Remove a surface from the UI |
get_catalogs | Get the catalogs supported by a client session (index + type defs) |
get_component_details | Get full property details for one or more components |
get_function_details | Get full usage details for one or more functions |
get_pending_actions | Drain pending user actions from a specific session (polling fallback) |
get_all_pending_actions | Drain pending actions across all sessions owned by this agent |
list_sessions | List sessions owned by this agent with surface and action details |
claim_session | Claim a client session for this agent |
release_session | Release a claim on a session |
get_catalogs
Section titled “get_catalogs”Agents must call get_catalogs(sessionId) at the start of a session before calling create_surface. It returns a slim index of available catalogs — component and function names, descriptions, and type definitions — plus the catalogId needed for create_surface.
Call get_component_details or get_function_details before using any component or function to get the full property reference.
get_data_model
Section titled “get_data_model”Requests the current client-side data model for a surface. Sends a getDataModel message downstream; the client responds with the full model state. This works regardless of whether sendDataModel was enabled on the surface — useful for on-demand inspection without the overhead of sending the data model with every action.
get_component_tree
Section titled “get_component_tree”Requests the current component tree for a surface from the client. Sends a getComponentTree message downstream; the client responds with the flat list of components and the root component ID. Returns { success, surfaceId, components, rootId }.
This is useful after reconnects or agent restarts to verify the current rendered state, or when the agent needs to understand the current layout before deciding whether to update or replace it. Both get_data_model and get_component_tree are Freesail extensions to the A2UI protocol — they provide a reverse path from client to agent that the spec does not define.
Surface naming rules
Section titled “Surface naming rules”| Type | Pattern | Agent permissions |
|---|---|---|
| Agent-managed | Alphanumeric + underscores (e.g. workspace) | Full control |
| Client-managed | Starts with __ (e.g. __chat) | update_data_model and update_components only |
HTTPS / TLS
Section titled “HTTPS / TLS”The gateway runs plain HTTP by default. For production, place NGINX in front to handle TLS termination for both ports. See the Developer Guide for a sample NGINX configuration.
Environment Variables
Section titled “Environment Variables”| Variable | Description |
|---|---|
CATALOG_LOG_DIR | Directory to write catalog prompt logs to. Overridden by catalogLogDir in config. |