# @aerostack/gateway

Connect [Aerostack](https://aerostack.dev) to your local AI runtime: pair from your phone, approve risky tool calls with a tap, and let your agent reach hundreds of MCP servers through one URL — no per-tool config, no token-paste dance.

[![License: MIT](https://img.shields.io/badge/LICENSE_//_MIT-3b5bdb?style=for-the-badge&labelColor=eff6ff)](https://opensource.org/licenses/MIT)
[![npm](https://img.shields.io/npm/v/@aerostack/gateway?style=for-the-badge&color=3b5bdb&labelColor=eff6ff)](https://www.npmjs.com/package/@aerostack/gateway)

## What it does

Aerostack is the control plane for your AI agents. This package is the **machine-side bridge** that connects your local agent runtime (OpenClaw, Claude Code, Claude Desktop, Cursor, Cline, Goose, Windsurf, and any other MCP client) to an Aerostack Workspace.

Once paired, your agent gets:

- **Mobile approval gates** — tap to approve risky tool calls from the [Aerostack mobile app](https://apps.apple.com/app/aerostack)
- **Local Guardian** — approval gates for **local** operations the agent runs on your machine: `rm -rf`, `git push`, deploys, file deletions, etc.
- **All tools in one place** — composed from many MCP servers, addressed through a single workspace
- **Centralized OAuth** — 27+ providers managed by Aerostack, never embedded in your agent
- **Per-tool permissions** — workspace tokens scope exactly which tools are reachable
- **Usage tracking & audit** — every tool call logged and metered

## Quick Start

There are two ways to use this package. Pick the one that matches your setup.

### Path A — OpenClaw + Aerostack Mobile (recommended)

If you run [OpenClaw](https://openclaw.ai) on your machine and want full mobile-driven approvals + chat:

```bash
# 1. Install once, globally
npm install -g @aerostack/gateway

# 2. Pair this machine — opens an interactive QR/code flow
aerostack-gateway init
```

`init` will:

1. Print a 6-digit pairing code (and a QR if your terminal supports it).
2. Open the **Aerostack mobile app** (iOS / Android) → Spaces → "+ connect another machine" → scan/enter the code.
3. Auto-write your workspace credentials, install the always-on LaunchAgent (macOS) / systemd unit (Linux), and add the Aerostack MCP entry to `~/.openclaw/openclaw.json`.

Done. Your agent's risky tool calls now appear on your phone for approval.

To verify:

```bash
aerostack-gateway status
```

### Path B — Plain MCP client (Claude Code / Desktop / Cline / etc.)

If you don't run OpenClaw and just want to connect an MCP client to a workspace:

```bash
npm install -g @aerostack/gateway
```

Get your **workspace URL** and **token** from the [Aerostack Admin Dashboard](https://app.aerostack.dev) → your workspace → **Connect**. The URL looks like:

```
https://api.aerostack.dev/api/gateway/ws/<workspace-slug>
```

**Claude Code:**

```bash
claude mcp add aerostack -- aerostack-gateway \
  --env AEROSTACK_WORKSPACE_URL=https://api.aerostack.dev/api/gateway/ws/your-slug \
  --env AEROSTACK_TOKEN=mwt_your_token_here
```

**Claude Desktop** — `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "aerostack": {
      "command": "aerostack-gateway",
      "env": {
        "AEROSTACK_WORKSPACE_URL": "https://api.aerostack.dev/api/gateway/ws/your-slug",
        "AEROSTACK_TOKEN": "mwt_your_token_here"
      }
    }
  }
}
```

**Cline (VS Code)** — settings under `cline.mcpServers`:

```json
{
  "aerostack": {
    "command": "aerostack-gateway",
    "env": {
      "AEROSTACK_WORKSPACE_URL": "https://api.aerostack.dev/api/gateway/ws/your-slug",
      "AEROSTACK_TOKEN": "mwt_your_token_here"
    }
  }
}
```

**Cursor / Goose / any HTTP-native MCP client** — point at the workspace URL directly with `Authorization: Bearer mwt_...`. The bridge isn't needed.

To verify connection:

```bash
AEROSTACK_WORKSPACE_URL="..." AEROSTACK_TOKEN="..." aerostack-gateway --check
```

## CLI Reference

| Command | What it does |
|---|---|
| `aerostack-gateway init` | Interactive pair flow. Writes token + LaunchAgent + MCP entry. |
| `aerostack-gateway status` | Paired? Connected? Versions? Service state? |
| `aerostack-gateway doctor` | Run preflight checks and offer fixes. |
| `aerostack-gateway logs [--follow]` | Tail connector + exec-daemon logs. |
| `aerostack-gateway unpair` | Stop services, wipe pairing state, restart OpenClaw gateway. |
| `aerostack-gateway --check` | Legacy MCP-bridge connection check (Path B). |
| `aerostack-gateway --version` | Print version and exit. |

## How It Works

When paired (Path A), three processes run on your machine — all managed by your OS service manager (launchd on macOS, systemd on Linux):

```
┌──────────────────────────────── your machine ───────────────────────────────┐
│                                                                             │
│  dev.aerostack.connector       persistent gateway-WS ↔ chat-relay-WS bridge │
│  dev.aerostack.exec-daemon     owns the exec-approvals socket               │
│  dev.aerostack.watchdog        keeps the other two healthy                  │
│                                                                             │
│  Plus: an MCP child spawned by OpenClaw from ~/.openclaw/openclaw.json      │
│                                                                             │
└──────────────────────────────────┬──────────────────────────────────────────┘
                                   │ HTTPS + WSS
                                   ▼
                         ┌──────────────────────┐
                         │  Aerostack Worker    │
                         └──────────┬───────────┘
                                    │
                         ┌──────────▼───────────┐
                         │  Aerostack Mobile    │
                         │  (iOS / Android)     │
                         └──────────────────────┘
```

When unpaired (Path B), the bridge runs as a stdio MCP server child of your AI tool — no LaunchAgents, no always-on processes. Same package, two modes.

## Local Guardian

Approval gates for **local operations** — file deletion, destructive shell commands, git push, deploys. The agent calls `aerostack__local_guardian` before acting on your machine; you get a push notification on your phone and approve or reject in seconds.

| Category | Examples |
|---|---|
| `file_delete` | Deleting or overwriting files |
| `shell_destructive` | `rm -rf`, `DROP TABLE`, etc. |
| `git_push` | `git push`, force push, `git reset --hard` |
| `config_modify` | `.env`, credentials, production configs |
| `deploy` | Deploy, publish, release to any environment |
| `database` | Direct database mutations outside migrations |

## Disconnect / Unpair

You can disconnect from the **mobile app** (Spaces → agent → "disconnect agent") or from the **CLI** (`aerostack-gateway unpair`). Both paths cleanly tear down the local connector and revoke the workspace token server-side. From mobile, the connector sees a `workspace_unpaired` WebSocket frame and tears down within ~25 ms — it doesn't sit polling a revoked token.

## Configuration

Path A doesn't need any of these — `init` writes them for you. Path B uses them as env vars on the MCP child:

| Variable | Required | Description |
|---|---|---|
| `AEROSTACK_WORKSPACE_URL` | Path B | `https://api.aerostack.dev/api/gateway/ws/<slug>` |
| `AEROSTACK_TOKEN` | Path B | Workspace token (`mwt_…`) — get from dashboard |
| `AEROSTACK_LOG_LEVEL` | No | `debug` / `info` (default) / `warn` / `error` |

## Troubleshooting

```bash
aerostack-gateway status     # is everything paired and connected?
aerostack-gateway doctor     # automated preflight + suggested fixes
aerostack-gateway logs -f    # tail the connector + exec-daemon
```

Common issues:

| Problem | Fix |
|---|---|
| `aerostack-gateway: command not found` | `npm install -g @aerostack/gateway` |
| Path B: `AEROSTACK_WORKSPACE_URL is required` | The MCP client isn't passing env vars. Check your client's `env` config block. |
| Token shows `401` in `status` | Pairing was revoked. Re-pair: `aerostack-gateway init`. |
| Mobile shows daemon offline but `status` shows running | Likely a transient WS reconnect. Wait 30 s; if it persists, run `doctor`. |
| OpenClaw: tools not showing | Send any message via Telegram or another channel to initialize the session. |

## Supported MCP Methods

`tools/list`, `tools/call` (with approval gates), `resources/list`, `resources/read`, `prompts/list`, `prompts/get`.

## Requirements

- Node.js 22+
- macOS or Linux (Windows support is best-effort — file an issue)
- An Aerostack account ([sign up](https://app.aerostack.dev))

## Links

- [Aerostack Docs](https://docs.aerostack.dev)
- [Aerostack Admin](https://app.aerostack.dev)
- [Aerostack Mobile](https://aerostack.dev/mobile)
- [MCP Specification](https://modelcontextprotocol.io)

## License

MIT
