Create a tunnel
The CLI (fastest path)
Section titled “The CLI (fastest path)”The CLI is the primary way to run a tunnel — it both creates the local↔public forwarding session and prints your URL.
npx @maxoperf/tunnel http 3000✔ guest tunnel online https://tunnel-swift-otter-7f3.maxoperf.com → http://127.0.0.1:3000↑ sign up for a named subdomain, more tunnels, access controls & capture: https://maxoperf.com/signup12:00:01 GET /api/users 200 12ms 1.2kBNo token, no account. A durable guest identity is saved to ~/.maxoperf/tunnel.json (file mode 0600), so re-running the command reuses the same URL.
Create the tunnel first (console, API, or MCP — see below), then run the CLI with its one-time client token:
npx @maxoperf/tunnel http 3000 --token mptt_example_token --name myapp✔ tunnel online https://tunnel-myapp.maxoperf.com → http://127.0.0.1:3000CLI options
Section titled “CLI options”| Flag / env | Purpose |
|---|---|
--token <mptt_…> / MAXOPERF_TUNNEL_TOKEN | Tunnel client token. Omit for a guest tunnel. |
--name <name> | Preferred subdomain label (informational — the URL is set server-side at create time). |
--server <host:port> / MAXOPERF_TUNNEL_SERVER | Gateway address (default app.maxoperf.com:443, TLS auto-detected). |
--api-url <url> / MAXOPERF_API_URL | Platform API origin, used for guest tunnels (default https://app.maxoperf.com). |
--local-host <host> | Local host to forward to (default 127.0.0.1). |
Credential resolution order: --token → MAXOPERF_TUNNEL_TOKEN → the saved config-file account token → the saved config-file guest token → mint a brand-new guest. Ctrl-C closes the session cleanly so the tunnel flips offline immediately — it does not linger as a zombie session. The CLI never prints or logs your token.
Create an account tunnel from the console
Section titled “Create an account tunnel from the console”- Open Tunnels in the left navigation and click Create tunnel.
- Enter a name — the DNS label that becomes
tunnel-<name>.maxoperf.com(lowercase letters, digits, hyphens; must be globally unique). - Optionally configure access controls (below), then save. The tunnel is created offline — it goes live the moment a client (the CLI, or your own gRPC client) connects with its token.
- Reveal the tunnel’s connection token from the tunnel detail page and run the CLI (or your client) with it.
tunnels-listWhat to show:MaxoPerf Tunnels list page showing tunnel rows with name, URL, online status, and a Create tunnel button
Tunnels list — each row shows the tunnel's URL and whether a client is currently connected (online).
tunnel-detail-overviewWhat to show:MaxoPerf tunnel detail page Overview tab showing the tunnel URL, online/offline status, and traffic statistics chart
Tunnel detail — Overview tab: status, URL, and live traffic statistics.
Create it from the REST API
Section titled “Create it from the REST API”curl -X POST https://app.maxoperf.com/v1/tunnels \ -H "Authorization: Bearer mpak_example_key" \ -H "X-Account-Id: acn-1234567890" \ -H "Content-Type: application/json" \ -d '{ "name": "myapp", "authMode": "basic", "basicAuth": { "username": "demo", "password": "s3cret" }, "allowIps": ["203.0.113.0/24"], "rateLimitRpm": 600, "maxBodyBytes": 10485760, "idleTimeoutSeconds": 3600, "captureMode": "headers" }'The 201 response returns the tunnel’s URL and a one-time clientToken (mptt_…) — it is never shown again, so copy it immediately. Other routes: GET /v1/tunnels, GET /v1/tunnels/:id, PATCH /v1/tunnels/:id (any config field except name), POST /v1/tunnels/:id/stop, POST /v1/tunnels/:id/start, DELETE /v1/tunnels/:id (stopped only), POST /v1/tunnels/:id/rotate-token.
Access controls
Section titled “Access controls”Configure these at create time or later via PATCH, from the tunnel’s Settings tab in the console:
| Control | What it does |
|---|---|
Auth mode — none / basic / bearer | Require HTTP basic auth or a bearer token before a request reaches your local server. |
| Allow / deny IPs | CIDR lists. An IP not in allowIps (when set) is blocked; an IP in denyIps is always blocked. |
Rate limit (rateLimitRpm) | Requests per minute before the tunnel starts responding 429. |
Max body size (maxBodyBytes) | Caps request/response body size the tunnel will proxy. |
Idle timeout (idleTimeoutSeconds) | How long the tunnel can sit with no traffic before it auto-stops. Default 3600s (1 hour). |
Expiry (expiresAt) | Optional absolute ISO-8601 timestamp after which the tunnel stops permanently. |
Reconnect and idle-shutdown behavior
Section titled “Reconnect and idle-shutdown behavior”- Idle or TTL auto-stop reactivates on reconnect. If a tunnel stopped itself because it went idle or hit its expiry, a client reconnecting with a valid token brings it straight back online, on the same URL — no separate “start” step needed. This is what makes the guest URL genuinely stable across restarts.
- A manual or plan-driven stop does not. If you (or MaxoPerf, for a plan-limit reason) explicitly stopped a tunnel, it stays stopped even if a client keeps retrying — you have to call
POST /v1/tunnels/:id/start(or use the console) to bring it back. This distinction exists specifically to stop a client’s automatic reconnect from silently bypassing a deliberate stop or a plan cap. - Dropped network ≠ stopped tunnel. If your local network blips, the CLI reconnects automatically with backoff and the tunnel’s public URL keeps working once it’s back — this isn’t a “stop” at all.
Statistics and request capture
Section titled “Statistics and request capture”Every account tunnel’s Overview tab shows a live traffic timeline: request counts, 4xx/5xx error rates, blocked-request counts, bytes in/out, and p50/p95/p99 latency. The Requests tab lists individual request events (when captureMode is headers or body) with the ability to replay a captured request straight from the console.
captureMode | What’s recorded |
|---|---|
none (guest default) | Only aggregate stats — no per-request detail. |
headers | Per-request metadata + headers, but not the body. |
body | Full per-request capture including body (subject to the maxBodyBytes cap). |
Claim a guest tunnel
Section titled “Claim a guest tunnel”Signed up after starting with guest mode? Attach your running guest tunnel to your account without losing its URL:
curl -X POST https://app.maxoperf.com/v1/tunnels/<id>/claim \ -H "Authorization: Bearer mpak_example_key" \ -H "X-Account-Id: acn-1234567890" \ -H "Content-Type: application/json" \ -d '{ "guestToken": "mptt_g_example_guest_token" }'The tunnel keeps its URL, moves from the guest cap to your plan’s tunnel limit, and immediately unlocks named-subdomain-style configuration (access controls, capture, idle-timeout tuning).
Next steps
Section titled “Next steps”- Tunnels overview — guest vs. account tunnels, what every tunnel gets.
- Virtual services — expose a mocked dependency the same way a tunnel exposes a local port.